We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
一个 Promise 就是一个代表了异步操作最终完成或者失败的对象。 promise本质上是一个绑定了回调的对象,而不是将回调传进函数内部。
通过在浏览器中打印Promise对象查看其结构 Promise 流程示意图
以promise-polyfill的为例,来分析一下Promise的实现
function Promise(fn) { //构造函数 new Promise(function(){}) if (!(this instanceof Promise)) //如果没有通过构造函数调用报错 throw new TypeError('Promises must be constructed via new'); //构造函数参数不是函数 报错 if (typeof fn !== 'function') throw new TypeError('not a function'); /** @type {!number} */ //0 表示 pending: 初始状态,既不是成功,也不是失败状态。 //1 表示 fulfilled: 意味着操作成功完成。 //2 表示 rejected: 意味着操作失败 this._state = 0; /** @type {!boolean} */ this._handled = false; /** @type {Promise|undefined} */ // value 表示异步操作的返回值 this._value = undefined; /** @type {!Array<!Function>} */ // deferreds 表示回调的事件队列 this._deferreds = []; doResolve(fn, this); }
function doResolve(fn, self) { //fn 为new Promise(fn) 参数 var done = false; try { fn( function (value) { if (done) return; done = true; resolve(self, value); //通过主动调用返回一个Promise 对象 }, function (reason) { if (done) return; done = true; reject(self, reason); } ); } catch (ex) { if (done) return; done = true; reject(self, ex); } }
function resolve(self, newValue) { //self 创建的promise 对象 ,value 异步或同步的返回值 try { // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure //resolve 传参的几种情况 //1. 传入创建出来的Promise 对象,原生会报Promise对象不能链式传递的错误 //2. 传入带有then方法的对象对象或者函数 //3. 传入另一个Promise对象会直接返回传入对象 //4. 其他基本类型值或者引用类型值 if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.'); if ( newValue && (typeof newValue === 'object' || typeof newValue === 'function') ) { var then = newValue.then; //如果返回的是一个Promise对象 if (newValue instanceof Promise) { self._state = 3; self._value = newValue;//self 为回调队列中,下个未绑定值的Promise finale(self); return; } else if (typeof then === 'function') { doResolve(bind(then, newValue), self); return; } } //其他情况,Promise对象状态变1,表示已完成 self._state = 1; //保存同步或异步操作的返回值 self._value = newValue; finale(self); } catch (e) { reject(self, e); } }
//finale 表示最终的意思,在有resolve的结果后就可以执行then方法中的回调, //then方法同样调用下面的handle方法,讲回调函数放入_deferreds事件队列中,在稍后介绍then方法 function finale(self) { //promise 状态为错误且回调队列中没有事件 if (self._state === 2 && self._deferreds.length === 0) { Promise._immediateFn(function () { if (!self._handled) { Promise._unhandledRejectionFn(self._value); } }); } //如果回调队列中有事件则通过handle函数循环释放,也就是原生中的微任务队列 for (var i = 0, len = self._deferreds.length; i < len; i++) { handle(self, self._deferreds[i]); } //全部执行后清空事件队列 self._deferreds = null; }
//handle 用来执行事件队列中的回调函数,也就是then添加进去的方法 //handle 方法把添加事件和释放事件一起在handle中处理 //所以finale 中执行事件队列中的方法会调用handle,then中添加事件到队列中也是调用handle方法 function handle(self, deferred) { //如果返回值为Promsie对象,当前Promise赋值为返回的Promise对象 while (self._state === 3) { self = self._value; } //状态为0初始状态时,把事件加入队列中.如果返回值为Promsie对象,在上一步复制后也会走到这里,实现的是原生Promise在函数里面,和外面都可以使用then的功能,把后面的回调添加到新的Promise回调里面,也就是为什么需要循环释放promise队列哪怕他每次只添加了一个。 if (self._state === 0) { self._deferreds.push(deferred); return; } self._handled = true; // _immediateFn 是一个异步函数,类似于settimeout,在最后统一介绍其他函数的作用 //为什么在拿到值以后还要异步执行? Promise._immediateFn(function () { //Promise 状态为1已完成 ,使用事件中onFulfilled var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected; if (cb === null) { (self._state === 1 ? resolve : reject)(deferred.promise, self._value); return; } var ret; try { //执行回调函数,传入异步或同步的返回值 ret = cb(self._value); } catch (e) { reject(deferred.promise, e); return; } // resolve(deferred.promise, ret); }); }
Promise.prototype.then = function (onFulfilled, onRejected) { var prom = new this.constructor(noop); handle(this, new Handler(onFulfilled, onRejected, prom)); return prom; };
一个可能有疑问的地方,为什么在finale中以为循环施法了then,方法添加的回调队列,当时在handle中执行完回调后还要,继续执行resolve,那不就所有的回调方法都执行了两次。
需要注意的是then方法每次返回一个新的Promise对象,而每个then方法添加的回调函数,都是绑定在在不同Promise对象上放入回调队列中的。保证回调队列的按顺序执行,在每一个回调执行后在执行下个回调,可控的拿到上一个回调的返回值
The text was updated successfully, but these errors were encountered:
No branches or pull requests
Promise实现原理
通过在浏览器中打印Promise对象查看其结构


Promise 流程示意图
以promise-polyfill的为例,来分析一下Promise的实现
doResolve
resolve
finale
handle
then
一个可能有疑问的地方,为什么在finale中以为循环施法了then,方法添加的回调队列,当时在handle中执行完回调后还要,继续执行resolve,那不就所有的回调方法都执行了两次。
需要注意的是then方法每次返回一个新的Promise对象,而每个then方法添加的回调函数,都是绑定在在不同Promise对象上放入回调队列中的。保证回调队列的按顺序执行,在每一个回调执行后在执行下个回调,可控的拿到上一个回调的返回值
The text was updated successfully, but these errors were encountered: