JS執行——Promise

Promise

Promise 是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理且更強大。它最早由社區提出並實現,ES6將其寫進了語言標準,統一了用法,並原生提供了Promise對象。

特點

  1. 對象的狀態不受外界影響 (3種狀態)
    • Pending狀態(進行中)
    • Fulfilled狀態(已成功)
    • Rejected狀態(已失敗)
  2. 一旦狀態改變就不會再變 (兩種狀態改變:成功或失敗)
    • Pending -> Fulfilled
    • Pending -> Rejected

用法

創建Promise實例

var promise = new Promise(function(resolve, reject){
    // ... some code
    
    if (/* 異步操作成功 */) {
        resolve(value);
    } else {
        reject(error);
    }
})

  Promise構造函數接受一個函數作爲參數,該函數的兩個參數分別是resolvereject。它們是兩個函數,由JavaScript引擎提供,不用自己部署。
  resolve作用是將Promise對象狀態由“未完成”變爲“成功”,也就是Pending -> Fulfilled,在異步操作成功時調用,並將異步操作的結果作爲參數傳遞出去;而reject函數則是將Promise對象狀態由“未完成”變爲“失敗”,也就是Pending -> Rejected,在異步操作失敗時調用,並將異步操作的結果作爲參數傳遞出去。

then

  Promise實例生成後,可用then方法分別指定兩種狀態回調參數。then 方法可以接受兩個回調函數作爲參數:

  1. Promise對象狀態改爲Resolved時調用 (必選)
  2. Promise對象狀態改爲Rejected時調用 (可選)

基本用法示例

function sleep(ms) {
    return new Promise(function(resolve, reject) {
        setTimeout(resolve, ms);
    })
}
sleep(500).then( ()=> console.log("finished"));

  這段代碼定義了一個函數sleep,調用後,等待了指定參數(500)毫秒後執行then中的函數。值得注意的是,Promise新建後就會立即執行。

執行順序

  接下來我們探究一下它的執行順序,看以下代碼:

let promise = new Promise(function(resolve, reject){
    console.log("AAA");
    resolve()
});
promise.then(() => console.log("BBB"));
console.log("CCC")

// AAA
// CCC
// BBB

  執行後,我們發現輸出順序總是 AAA -> CCC -> BBB。表明,在Promise新建後會立即執行,所以首先輸出 AAA。然後,then方法指定的回調函數將在當前腳本所有同步任務執行完後纔會執行,所以BBB 最後輸出

與定時器混用

  首先看一個實例:

let promise = new Promise(function(resolve, reject){
    console.log("1");
    resolve();
});
setTimeout(()=>console.log("2"), 0);
promise.then(() => console.log("3"));
console.log("4");

// 1
// 4
// 3
// 2

  可以看到,結果輸出順序總是:1 -> 4 -> 3 -> 2。1與4的順序不必再說,而2與3先輸出Promise的then,而後輸出定時器任務。原因則是Promise屬於JavaScript引擎內部任務,而setTimeout則是瀏覽器API,而引擎內部任務優先級高於瀏覽器API任務,所以有此結果。

拓展 async/await

async

  顧名思義,異步。async函數對 Generator 函數的改進,async 函數必定返回 Promise,我們把所有返回 Promise 的函數都可以認爲是異步函數。特點體現在以下四點:

  • 內置執行器
  • 更好的語義
  • 更廣的適用性
  • 返回值是 Promise

await

  顧名思義,等待。正常情況下,await命令後面是一個 Promise 對象,返回該對象的結果。如果不是 Promise 對象,就直接返回對應的值。另一種情況是,await命令後面是一個thenable對象(即定義then方法的對象),那麼await會將其等同於 Promise 對象。

混合使用

  先看示例:

function sleep(ms) {
    return new Promise(function(resolve, reject) {
        setTimeout(resolve,ms);
    })
}
async function handle(){
    console.log("AAA")
    await sleep(5000)
    console.log("BBB")
}

handle();

// AAA
// BBB (5000ms後)

  我們定義函數sleep,返回一個Promise。然後在handle函數前加上async關鍵詞,這樣就定義了一個async函數。在該函數中,利用await來等待一個Promise。

Promise優缺點

優點 缺點
解決回調 無法監測進行狀態
鏈式調用 新建立即執行且無法取消
減少嵌套 內部錯誤無法拋出

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章