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 回调放在进行宏任务队列的队尾,若队列非常长,那么回调迟迟得不到执行,造成的效果就是应用卡顿。所以就引入了微任务。

posted @ 2020-03-15 23:25  Ever-Lose  阅读(2509)  评论(0编辑  收藏  举报