let promise = new Promise((resolve, reject) => {
// when success, resolve
let value = 'success';
resolve(value);
// when an error occurred, reject
reject(new Error('Something happened!'));
});
Promise.prototype.then = function(onFulfilled, onRejected) {
if (this.constructor !== Promise) {
return safeThen(this, onFulfilled, onRejected);
}
var res = new Promise(noop);
handle(this, new Handler(onFulfilled, onRejected, res));
return res;
};
function safeThen(self, onFulfilled, onRejected) {
return new self.constructor(function (resolve, reject) {
var res = new Promise(noop);
res.then(resolve, reject);
handle(self, new Handler(onFulfilled, onRejected, res));
});
}
作者:holyZheng 转载请注明出处
背景
Promise本身是一个异步编程的方案,让处理过程变得更简单。es6引入promise特性来处理JavaScript中的异步场景。以前,处理异步最常用的方法就是回调函数,但是当过程稍微复杂一点,多个异步操作集中在一起的时候,就容易出现一个回调金字塔的情况,可读性和可维护性都非常差,比如:
Promise可以避免这种情况发生,将回调嵌套转变为链式调用,避免回调金字塔的出现。
Promise基本用法
Promise有4种状态:
settled——完成状态
可以通过then方法来处理返回的结果
promise.then(response => { console.log(response); }, error => { console.log(error); });
对reject状态返回的结果的处理,可以通过then的第二个参数,也可以通过catch方法
同时处理多个promise,不关注执行顺序可以用all方法
Promise.all()接收一个promises数组,当全部fulfiled时,返回一个按顺序的数组 当其中一个reject时,返回第一个rejected的值 或者race方法,接收多个promise实例,组成一个新的promise,有一个变化的时候,外层promise跟着变化。 快捷方法:
——参考ES6 Promise
原理
为了学习promise内部原理,最好是看其实现源码,then/promise是github上一个遵循promise A+规范的库,其核心代码在core文件中。那么就从这个库来学习。
可以看到,我通过Promise构造函数实例化一个promise对象,在对参数进行检查后,我们会执行doResolve(fn, this)方法,顺藤摸瓜看看doResolve函数做了什么
这里就是将两个回调函数分别传给 fn 的 两个参数,并确保他们只执行一次。 接下来就要看它的resolve方法。
resolve除了一些判断外,就是根据接收到的参数的类型来修改state的值。如果接收到promise对象或thenable对象,state转为3,并使用它的结果,如果时其他如字符串类型等,state转为1,直接使用该值。 有了结果之后,就要看一下then方法了。
then方法也很简单,就是用Handler包装一个对象
然后调用handle方法。整个过程就是创建一个新的promise,调用handle方法,将新的promise返回,以便实现链式调用。 下面看一下handle方法。
handle方法就是根据state的值和_deferredState ,来决定要做的事情,我们来捋一捋,当我们的resolve方执行,state转为1时,我们会进入then方法,然后进入handle方法,因为state为1,可以看到我们会直接进入handleResolved方法。
看看handleResolved函数是做什么的
过滤掉添加判断,handleResolved就是使用结果值self._value调用then中的相应回调(成功或失败)。 那当resolve接收的是普通值得时候整个运行过程就知道了。
当我们resolve接收到得是一个promise或thenable对象时,我们进入到handle后,会进入while循环,直到self指向接收到的promise,以接收到的promise的结果为标准,在接收到的promise的 state===0 阶段我们会将原始promise中拿到得onFulfilled以及onRejected回调方法(包含在deferred对象中),添加到接收到的promise的 _deferreds 中,然后return。 存在 _deferreds 中的回调在什么时候执行呢? 我们可以看到无论时resolve还是reject,只要状态改变都会执行 finale 方法,我们看一下 finale
因为每次执行此方法都是在state状态改变的时候,所以进入handle函数后会直接进入handleResolved方法,然后使用self._value的结果值执行对应的回调函数(onFulfilled 或 onRejected)。 最后看看reject
这下清晰多了,再来捋一捋,![promise](https://raw.githubusercontent.com/HolyZheng/holyZheng-blog/master/images/promise.png)
总结