深入理解ES6筆記(十一)Promise與異步編程

主要知識點:Promise生命週期、Promise基本操作、Promise鏈、響應多個Promise以及集成Promise
圖片描述
《深入理解ES6》筆記 目錄

異步編程

JavaScript引擎中,只有一個主線程,當執行JavaScript代碼塊時,不允許其他代碼塊執行,而事件機制和回調機制的代碼塊會被添加到任務隊列(或者叫做堆棧)中,當符合某個觸發回調或者事件的時候,就會執行該事件或者回調函數。

事件模型

瀏覽器初次渲染DOM的時候,我們會給一些DOM綁定事件函數,只有當觸發了這些DOM事件函數,纔會執行他們:

let button = document.getElementById("my-btn");
button.onclick = function(event) {
    console.log("Clicked");
};

回調模式

當 Node.js 被創建時,它通過普及回調函數編程模式提升了異步編程模型。回調函數模式類似於事件模型,因爲異步代碼也會在後面的一個時間點才執行:

readFile("example.txt", function(err, contents) {
    if (err) {
        throw err;
    }
    console.log(contents);
});
console.log("Hi!");

如果回調過多,會陷入回調地獄;

Promise 基礎

Promise可以當做是一個佔位符,表示異步操作的執行結果。函數可以返回一個Promise,而不必訂閱一個事件或者向函數傳遞一個回調函數。

// readFile 承諾會在將來某個時間點完成
let promise = readFile("example.txt");

在此代碼中, readFile() 實際上並未立即開始讀取文件,這將會在稍後發生。此函數反而會返回一個 Promise 對象以表示異步讀取操作,因此你可以在將來再操作它。

Promise 的生命週期

Promise的生命週期:進行中(pending),已經完成(fulfilled),拒絕(rejected)
每個 Promise 都會經歷一個短暫的生命週期,初始爲掛起狀態(pending state) ,這表示異步操作尚未結束。一個掛起的 Promise 也被認爲是未決的(unsettled )。一旦異步操作結束, Promise就會被認爲是已決的(settled ) ,並進入兩種可能狀態之一:

  1. 已完成(fulfilled ) : Promise 的異步操作已成功結束;
  2. 已拒絕(rejected ) : Promise 的異步操作未成功結束,可能是一個錯誤,或由其他原因導致。

內部的[[PromiseState]] 屬性會被設置爲"pending" 、 "fulfilled" 或 "rejected",以反映Promise的狀態。該屬性並未在 Promise 對象上被暴露出來,因此你無法以編程方式判斷 Promise 到底處於哪種狀態。不過你可以使用then()方法在 Promise 的狀態改變時執行一些特定操作。

  • then()

then() 方法在所有的 Promise 上都存在,並且接受兩個參數。第一個參數是 Promise 被完成時要調用的函數,與異步操作關聯的任何附加數據都會被傳入這個完成函數。第二個參數則是 Promise 被拒絕時要調用的函數:

let promise = readFile("example.txt");
promise.then(function(contents) {
    // 完成
    console.log(contents);
}, function(err) {
    // 拒絕
    console.error(err.message);
});
promise.then(function(contents) {
    // 完成
    console.log(contents);
});
promise.then(null, function(err) {
    // 拒絕
    console.error(err.message);
});
  • catch() 方法

其行爲等同於只傳遞拒絕處理函數給 then()

promise.catch(function(err) {
    // 拒絕
    console.error(err.message);
});
// 等同於:
promise.then(null, function(err) {
    // 拒絕
    console.error(err.message);
});

創建未決的 Promise

Promise 使用 Promise 構造器來創建:

// Node.js 範例
let fs = require("fs");
function readFile(filename) {
    return new Promise(function(resolve, reject) {
        // 觸發異步操作
        fs.readFile(filename, { encoding: "utf8" }, function(err, contents) {
            // 檢查錯誤
            if (err) {
                reject(err);
                return;
            }
            // 讀取成功
            resolve(contents);
        });
    });
}
let promise = readFile("example.txt");
// 同時監聽完成與拒絕
promise.then(function(contents) {
    // 完成
    console.log(contents);
}, function(err) {
    // 拒絕
    console.error(err.message);
});

romise構造函數接受一個函數作爲參數,該函數的兩個參數分別是resolve和reject。它們是兩個函數,由 JavaScript 引擎提供,不用自己部署。
執行器會在 readFile() 被調用時立即運行

let promise = new Promise(function(resolve, reject) {
    console.log("Promise");
    resolve();
});
console.log("Hi!");

//輸出結果
Promise
Hi!

創建已決的 Promise

Promise.resolve()

Promise.resolve()方法接收一個參數,並會返回一個處於已完成狀態的 Promise ,在then()方法中使用完成處理函數才能提取該完成態的Promise傳遞的值,例如:

let promise = Promise.resolve(42);
promise.then(function(value) {
    console.log(value); // 42
});

Promise.reject()

可以使用Promise.reject()方法來創建一個已拒絕狀態的Promise,同樣只有在拒絕處理函數中或者catch()方法中才能接受reject()方法傳遞的值:

let promise = Promise.reject(42);
promise.catch(function(value) {
    console.log(value); // 42
});
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章