JS 來實現一個 Promise


promise A+ 規范簡述

  • 一個promise必須有3個狀態,pending,fulfilled(resolved),rejected當處於pending狀態的時候,可以轉移到fulfilled(resolved)或者rejected狀態。當處於fulfilled(resolved)狀態或者rejected狀態的時候,就不可變。
  • 一個promise必須有一個then方法,then方法接受兩個參數,resolve和reject
  • 實現鏈式調用,then方法必須返回一個promise

promise A+ 源碼

Promise 源碼:https://github.com/then/promise/blob/master/src/core.js

一個簡單的實現

// this promise code refered to this blog
// http://www.cnblogs.com/liuzhenwei/p/5235473.html
var Promise = function (fn) {
    var state = 'pending';
    var doneList = [];
    var failList= [];
    this.then = function(done ,fail){
        switch(state){
            case 'pending':
                doneList.push(done);
                //每次如果沒有推入fail方法,我也會推入一個null來占位
                failList.push(fail || null);
                return this;
                break;
            case 'fulfilled':
                done();
                return this;
                break;
            case 'rejected':
                fail();
                return this;
                break;
        }
    }
    function tryToJson(obj) {
        var value;
        try {
            value = JSON.parse(obj);
        } catch (e) {
            value = obj;
        }
        return value
    }
    function resolve(newValue){
        state = 'fulfilled';
        setTimeout(function(){
            var value = tryToJson(newValue);
            for (var i = 0; i < doneList.length; i++){
                var temp = doneList[i](value);
                if (temp instanceof Promise) {
                    var newP = temp;
                    for (i++; i < doneList.length; i++) {
                        newP.then(doneList[i], failList[i]);
                    }
                } else {
                    value = temp;
                }
            }
        }, 0);
    }
    function reject(newValue){
        state = 'rejected';
        setTimeout(function(){
            var value = tryToJson(newValue);
            var tempRe = failList[0](value);
            //如果reject里面傳入了一個promise,那么執行完此次的fail之后,將剩余的done和fail傳入新的promise中
            if(tempRe instanceof Promise){
                var newP = tempRe;
                for (i=1;i<doneList.length;i++) {
                    newP.then(doneList[i],failList[i]);
                }
            } else {
                //如果不是promise,執行完當前的fail之后,繼續執行doneList
                value = tempRe;
                doneList.shift();
                failList.shift();
                resolve(value);
            }
        }, 0);
    }

    fn(resolve,reject);
}

其實是把then方法里的回調函數分別推入doneList和failList中,然后在promiFn執行完畢后開始調用 function resolve(newValue){} 里更改state狀態為fulfilled並且執行doneListi;

var promiFn = function (resolve, reject) {
    setTimeout(function () {
        resolve(1)
    }, 0)
};
new Promise(promiFn)
.then(function (d) {
    console.log(d)   
}, function (e) {
    console.log(e);
})

promise 鏈式調用

let bodyToJson = null;
request('http:www.baidu.com')
.then((d) => {
    return otherPromise;
})
.then((d) => {
    return anotherPromise
})
.then((d) => {
    // ...
})
.catch((err) => {
    // ...
});

還缺的 API

  • Promise.all
  • Promise.race
  • Promise.prototype.catch
  • Promise.prototype.finally

等待完善。

問題:為什么 promise 需要引入微任務

Promise 中的執行函數是同步進行的,但是里面存在着異步操作,在異步操作結束后會調用 resolve 方法,或者中途遇到錯誤調用 reject 方法,這兩者都是作為微任務進入到 EventLoop 中。但是你有沒有想過,Promise 為什么要引入微任務的方式來進行回調操作?

若 promise 回調放在進行宏任務隊列的隊尾,若隊列非常長,那么回調遲遲得不到執行,造成的效果就是應用卡頓。所以就引入了微任務。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM