模拟ES6 Promise的轻量级实现

Promise是ES6提供的原生的异步编程解决方案,它的出现主要是为了解决回调地狱实现异步编程的糟糕语法。最早是由社区提出并实现的。本文提供了一个轻量级的Promise实现方式,主要想解释下Promise实现的主要原理。至于更细节的部分,本文不做阐述。

我已经将该轻量级的Promise实现放到了Gist上面:

https://gist.github.com/licaomeng/528d0a63c3305531c5b36c138fea17dc

function MyPromise(fn) {
    this.resolve;
    this.reject;
    _this = this;
    setTimeout(function () {
        fn(_this.resolveFunc.bind(_this), _this.rejectFunc.bind(_this));
    }, 0)
}

MyPromise.prototype = {
    then: function (resolve, reject) {
        this.resolve = resolve;
        this.reject = reject;
    },
    resolveFunc: function (value) {
        this.resolve(value);
    },
    rejectFunc: function (value) {
        this.reject(value);
    }
}


new MyPromise(function (resolve, reject) {
    var flag = Math.round(Math.random())
    if (flag) {
        resolve(flag);
    } else {
        reject(flag);
    }
}).then(function (resolve) {
    console.log(resolve);
}, function (reject) {
    console.log(reject);
})

可以看到,Promise是一个容器,对异步操作进行了封装,实际上还是通过回调函数实现的异步调用。

下面就来具体解释下轻量级Promise的原理。

首先new MyPromise对象的时候传入了一个匿名函数,这个匿名函数有两个参数分别是resolve和reject,用来改变Promise的状态。

resolve: pending -> fullfilled

reject:      pending -> rejected

Promise new之后 resolve和reject这两个方法会被"立即"执行,这两个函数的定义在哪里呢?在prototype里面!即 resolveFunc rejectFunc.

那这两个函数调用之后会发生什么呢?就会分别回调then方法中的两个匿名函数。

那么问题来了,刚才说了,new Promise的时候传入的匿名函数会被立即执行,而then方法是之后调用的,那么怎么才能调用到then方法中的两个匿名函数呢?这里就涉及到setTimeout调用时机的经典问题。setTimeout不在js主线程中,它由浏览单独的一个队列维护。调用的时机是,js主线程中的代码全部执行完后,再执行。所以可以看到上面的new Promise传入的方法外面包了setTimeout:

setTimeout(function () {
    fn(_this.resolveFunc.bind(_this), _this.rejectFunc.bind(_this));
}, 0)

也就是等then方法中的resolve, reject 方法注册完毕后,再来进行调用。

可以看到,本质上Promise还是回调,只不过对调用方式进行了封装,让回调看上去串行了而已。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值