實現一個符合Promise/A+規範的Promise

簡要介紹:Promise容許咱們經過鏈式調用的方式來解決「回調地獄」的問題,特別是在異步過程當中,經過Promise能夠保證代碼的整潔性和可讀性。promise

本文主要介紹一下Promise/A+規範,並在此規範的基礎上,本身實現一個Promise。瀏覽器

1、Promise的使用

在瞭解Promise規範以前,咱們知道主流的高版本瀏覽器已經支持ECMA中的Promise.異步

建立一個promise實例:函數

let p1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve("success");
    }, 3000);
    console.log("this is a promise");
});
p1.then(value => {
    console.log(value);
});
// 輸出:
// 立馬打印:this is a promise
// 延遲3000ms後打印:success

上述是一個promise的實例,輸出內容爲,「this is a promise」,延遲3000ms後,輸出"success"。this

從上述的例子能夠看出,promise方便處理異步操做。此外promise還能夠鏈式的調用:prototype

let p2 = new Promise((resolve, reject) => {
    resolve();
});
p2.then(...).then(...).then(...);

此外Promise除了then方法外,還提供了Promise.resolve、Promise.all、Promise.race等等方法。code

2、Promise/A+規範

Promise/A+規範大體有如下內容:對象

1.術語
(1)"promise"是一個對象或者函數,該對象或者函數有一個then方法
(2)"thenable"是一個對象或者函數,用來定義then方法
(3)"value"是promise狀態成功時的值
(4)"reason"是promise狀態失敗時的值
咱們明確術語的目的,是爲了在本身實現promise時,保持代碼的規範性原型

2.要求
(1)一個promise必須有3個狀態,pending,fulfilled(resolved),rejected。
當處於pending狀態的時候,能夠轉移到fulfilled(resolved)或者rejected狀態。當處於fulfilled(resolved)狀態或者rejected狀態的時候,就不可變。
promise英文譯爲承諾,也就是說promise的狀態一旦發生改變,就永遠是不可逆的。it

(2)一個promise必須有一個then方法,then方法接受兩個參數:

promise1.then(onFulfilled, onRejected);

其中onFulfilled方法表示狀態從pending —> fulfilled(resolved)時所執行的方法,而onRejected表示狀態從pending —> rejected所執行的方法。

(3)爲了實現鏈式調用,then方法必須返回一個promise

promise2 = promise1.then(onFulfilled, onRejected);

3、實現一個符合Promise/A+規範的Promise

瞭解了Promise/A+規範以後,下面咱們來看如何實現一個Promise。
首先構造一個myPromise函數,關於全部變量和函數名,應該與規範中保持相同。

1.v1.0 初始版本myPromise

function myPromise(constructor) {
    let self = this;
    self.status = 'pending';
    self.value = undefined; // 成功時的值
    self.reason = undefined; // 失敗時的值
    function resolve (value) {
        // 1.確保狀態只能由 pending 改成 resolved
        if (self.status === 'pending') {
            self.value = value;
            self.status = 'resolved';
        }
    }
    function reject (reason) {
        // 2.確保狀態只能由 pending 改成 rejected
        if (self.status === 'pending') {
            self.reason = reason;
            self.status = 'rejected';
        }
    }
    try {
        constructor(resolve, reject);
    } catch(e) {
        reject(e);
    }
}

同時,須要在myPromise的原型上定義鏈式調用的then方法:

myPromise.prototype.then = function (onFullfilled, onRejected) {
        let self = this;
        switch (self.status) {
            case 'resolved':
                onFullfilled(self.value);
                break;
            case 'rejected':
                onRejected(self.reason);
                break;
        }
    };

上述就是一個初始版本的myPromise,在myPromise裏發生狀態改變,而後在相應的then方法裏面根據不一樣的狀態能夠執行不一樣的操做。

let mp = new myPromise(function (resolve, reject) {
    resolve(1);
    // reject('err msg');
});
mp.then(function (res) {
    console.log(res);
}, function (err) {
    console.log(err);
});
// 輸出 1

可是這裏myPromise沒法處理異步的resolve。好比:

let mp1 = new myPromise(function (resolve, reject) {
    setTimeout(() => {
        resolve(2);
    }, 2000);
});
mp1.then(function (res) {
    console.log(res);
});
// 無輸出

2.v2.0基於觀察模式實現

...

相關文章
相關標籤/搜索