Promise

  • promise可封裝函式,執行後可取得執行狀態,並回傳被封裝函式的結果。

  • 通過鏈式調用,可依序執行函式,簡化多層的callback帶來的複雜性。

  • Promise處理的事項多半來自外部,所以會藉由回傳結果來進行下一步的動作。

  • 在ES6 Promise標準中,實作內容只有一個建構函式與一個then方法、一個catch方法,再加上四個必需以Promise關鍵字呼叫的API,Promise.resolve、Promise.reject、Promise.all、Promise.race。

  • Promise物件最後的結果要不然就用一個回傳值來fulfilled(實現),要不然就用一個理由(錯誤)來rejected(拒絕)。

fetch使用Promise架構,只有在網路連線發生問題才會轉為rejected(拒絕)狀態,只要是伺服器有回應都算已實現狀態。

  • promise物件必定是以下三種狀態中的其中一種: pending(等待中)、fulfilled(已實現)或rejected(已拒絕)。

//-----Promise語法結構如下:------
//Promise傳入函式稱為executor
const promise = new Promise(function(resolve, reject) {
  //自訂函數(被封裝在promise中)
  
  //下方的resolve和reject寫在函數中
  // 1.成功時執行,value是成功的參數,會傳到then
  resolve(value)
  // 2.失敗時執行,reason是失數的參數,會傳到then
  //reason(理由)通常是用Error物件
  reject(reason)
  
  
});

//then方法一樣用兩個函式當作傳入參數
//重點是會等待promise的函數執行結束後,才執行then的函數
//第1個onFulfilled函式是在promise物件有值的情況下才會執行(一定要設定)
//第2個onRejected函式則是在promise物件發生錯誤、失敗,才會執行。(範例沒設定)
promise.then(function(value) {
  // on fulfillment(已實現時)
}, function(reason) {
  // on rejection(已拒絕時)
})


//-----promise封裝範例-----
//將setTimeout封裝到promise中
function delay(ms) {   
  return new Promise(function (resolve, reject) {
    //被封裝的函式
    setTimeout(function () {
      resolve('我是成功傳下去的值');
    }, ms);
  });
}

//被封裝後的函數可以用promise的方法then或catch
delay(1000)
.then(function (value) {
  console.log(value);    // '我是成功傳下去的值'
})
.catch(function (error) {
  console.log(error);
});
  • 在JavaScript中如果回傳值相同的函式,可以使用連鎖的語法

//此範例無封裝函數,直接傳值
const promise = new Promise(function(resolve, reject) {
  resolve(1)
})

//resolve的傳入參數也會傳入為then的參數
//return的值是一直傳下去
promise.then(function(value) {
  console.log(value) // 1
  return value + 1
}).then(function(value) {
  console.log(value) // 2
  return value + 2
}).then(function(value) {
  console.log(value) // 4
})
  • then方法一樣用兩個函式當作傳入參數,但為了方便進行多個不同程式碼的連鎖,通常在只使用then方法時,都只寫第1個函式傳入參數。而錯誤處理通常交給另一個catch方法來做

//範例:多重then用return傳給下一個then
const p1 = new Promise((resolve, reject) => {
    resolve(4)
})

//使用then來逐一執行自訂的函數
p1.then((val) => {
        console.log(val) //4
        return val + 2
    })
    .then((val) => {
        console.log(val) //6
        throw new Error('error!')
    })
    .catch((err) => {      
        //catch無法抓到上個promise的回傳值
        console.log(err.message)
        //這裡如果有回傳值,下一個then可以抓得到
        //return 100
    })
    .then((val) => console.log(val, 'done')) //val是undefined,回傳值消息
// 建立一個函數回傳 promise 的標準範例
// 第一個要執行的函式,需返回 promise
function first(data){
   return new Promise(function(resolve, reject){
      if(data > 5){
          resolve(data)
       }else{
          reject('資料都是不大於5')
          //reject(new Error('資料都是不大於5'));
       }
   });
}

// 簡單的情況下,可簡寫為
function first(data) {
    if(data > 5) {
        return Promise.resolve(data);
    } else {
        return Promise.reject('資料都是不大於5');
    }
}


// 第二個要執行的函數
second(data){
    console.log(data)
}

// 整合二個函數,依序執行
// then( 回調函數 ) 
integration(){
   first(data).then(function(num) {
        second(num)
    }).catch(function(err) {
       console.log(err)
    })
}

Last updated