Promise 源码分析

2023-05-27 0 597

then/promise 工程项目是如前所述 Promises/A+ 国际标准同时实现的 Promise 库,从那个工程项目之中,他们上看 Promise 的基本原理是甚么,它是怎样努力做到的,进而更为熟识 Promise。

预测

从 index.js 之中晓得,它是先带出了 ./core.js,随即各别继续执行了其它文档的标识符,透过 requeire 的方式。

他们具体来说先想呵呵最此基础的 promise 用语

new Promise((resolve, reject) => { resolve(4);}).then(res => { console.log(res); // export 4});

Promise 中的国际标准

国际标准中明确规定:

1. Promise 第一类稳态为 Pending ,在被 resolve 或 reject 时,状况转变成 Fulfilled 或 Rejected2. resolve 转交获得成功的统计数据, reject 转交失利或严重错误的统计数据3. Promise 第一类要有两个 then 方式,且只拒绝接受三个可auth onFulfilled 、 onRejected

index.js
use strict;module.exports = require(./core.js);require(./done.js);require(./finally.js);require(./es6-extensions.js);require(./node-extensions.js);require(./synchronous.js);

他们先看 src/core.js

function Promise(fn) { // 推论 this很大得是object要不然就会收起,那个方式很大得要new出 if (typeof this !== object) { throw new TypeError(Promises must be constructed via new); } // 推论fn 很大得是两个函数 if (typeof fn !== function) { throw new TypeError(Promise constructor\s argument is not a function); } this._deferredState = 0; this._state = 0; this._value = null; this._deferreds = null; if (fn === noop) return; // 最终doResolve很关键 doResolve(fn, this);}

Promise 是两个构造方式,开始时,它进行了校验,确保了 fn 是两个函数,随即对一些变量进行了初始化,最后继续执行了 doResolve()

他们接着看 doResolve 那个方式。

/** * Take a potentially misbehaving resolver function and make sure * onFulfilled and onRejected are only called once. * * Makes no guarantees about asynchrony. */// // 确保`onFulfilled`和`onRejected`方式只调用一次// 不保证异步function doResolve(fn, promise) { var done = false; var res = tryCallTwo(fn, function (value) { // 如果done 为true 则return if (done) return; done = true; // 回调继续执行 resolve() resolve(promise, value); }, function (reason) { // 如果done 为true 则return if (done) return; done = true; reject(promise, reason); }); // res为truCallTwo()的返回值 // 如果done没有完成 并且 res 是 `IS_ERROR`的情况下 // 也会继续执行reject(),同时让done完成 if (!done && res === IS_ERROR) { done = true; reject(promise, LAST_ERROR); }}

doResolve 最关键的是继续执行了 tryCallTwo 方式,那个方式的第二,第三个参数都是回调,当继续执行回调后,done 为 true,同时各别会继续执行 resolve() 或者 reject() 方式。最后当 tryCallTwo 的返回值为 IS_ERROR 时,也会继续执行 reject() 方式。

他们先上看呵呵 tryCallTwo 方式

function tryCallTwo(fn, a, b) { try { fn(a, b); } catch (ex) { LAST_ERROR = ex; return IS_ERROR; }}

fn 实际就是 Promise 初始化时的匿名函数 (resolve, reject) => {} ,a,b则代表的是 resolve() 和 reject() 方式,当他们正常继续执行完 promise 函数时,则继续执行的是 resolve 则在 doResolve 中,他们当时继续执行的第二个参数被回调,如果收起, reject() 被继续执行,则第二个参数被回调。最后捕获了异常,当发生了收起时,会 return IS_ERROR ,非收起时会 return undinfed

再回到刚才的 doResolve 方式,当继续执行了第二个参数的回调之后,会继续执行 resolve 方式

function resolve(self, newValue) { // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure // 不能传递自己 if (newValue === self) { // 收起 return reject( self, new TypeError(A promise cannot be resolved with itself.) ); } // 的promise方式 读取newValue.then var then = getThen(newValue); if (then === IS_ERROR) { // 如果then IS_ERROR return reject(self, LAST_ERROR); } if ( // 如果then是self的then // 并且Promise then === self.then && // newValue 属于Promise newValue instanceof Promise ) { // _state为3 // 一般then之后走这里 // 继续执行then(newValue)返回了promise self._state = 3; // selft.value为newValue self._value = newValue; // 当state为3时继续执行 finale finale(self); return; } else if (typeof then === function) { doResolve(then.bind(newValue), self); return; } } self._state = 1; self._value = newValue; finale(self);}

在没有链式调用 then 的情况下(也就是只要两个 then)的情况下,会将内部状况 _state 设置成3,将传入值赋给内部变量 _value 最后会继续执行 final() 方式,要不然则会使用 doResolve 来调用 then

他们再上看下 reject

function reject(self, newValue) { // _state = 2为reject self._state = 2; self._value = newValue; if (Promise._onReject) { Promise._onReject(self, newValue); } finale(self);}

在 reject 之中他们的 _state 变更为了 2,同样最后 finale 被调用。

他们上看下 finale 函数

// 继续执行自己的deferredsfunction finale(self) { if (self._deferredState === 1) { handle(self, self._deferreds); self._deferreds = null; } if (self._deferredState === 2) { for (var i = 0; i < self._deferreds.length; i++) { // 遍历handle handle(self, self._deferreds[i]); } // 将deferred 置空 self._deferreds = null; }}

在该方式之中根据不同的 _deferredState ,会继续执行不同的 handle 方式。

他们再上看 handle 方式

function handle(self, deferred) { while (self._state === 3) { self = self._value; } // 如果有onHandle方式 则继续执行该方式 if (Promise._onHandle) { Promise._onHandle(self); } // (初始 _state 为0) if (self._state === 0) { // (初始 _deferredState 为0) if (self._deferredState === 0) { self._deferredState = 1; self._deferreds = deferred; return; } // 如果 _deferredState是1 则__deferreds是两个数组 if (self._deferredState === 1) { self._deferredState = 2; self._deferreds = [self._deferreds, deferred]; return; } // 当走到这里 _deferredState应该是2 将deferred // 插入到数组之中 self._deferreds.push(deferred); return; } handleResolved(self, deferred);}

这里比较关键的应该就是透过 deferredState 不同的状况,将 deferred 放入 deferreds 之中。另外当他们的 _state 不为0时,最终会继续执行 handleResolved 。

继续看 handleResolve() 方式

function handleResolved(self, deferred) { asap(function() { // _state为1时,cb = onFulfilled 否则 cb = onRejected var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected; if (cb === null) { if (self._state === 1) { resolve(deferred.promise, self._value); } else { reject(deferred.promise, self._value); } return; } var ret = tryCallOne(cb, self._value); if (ret === IS_ERROR) { reject(deferred.promise, LAST_ERROR); } else { resolve(deferred.promise, ret); } });}.then((res) => {}).catch((error) => {})

在那个方式之中,会根据他们任务 _state 的不同状况,来继续执行 onFulfilled 或者 onRejected 方式。当此方式调用时,也就是我们两个简单的 Promise 的结束。

回到刚才说的 Promise 构造方式结束的时候

设置了 Promise 函数的一些变量

Promise._onHandle = null;Promise._onReject = null;Promise._noop = noop;随即在Promise的原型上设置了then方式。Promise.prototype.then = function(onFulfilled, onRejected) { // 具体来说看这是谁构造的 如果不是promise // 则return 继续执行safeThen if (this.constructor !== Promise) { return safeThen(this, onFulfilled, onRejected); } // 如果是则初始化两个Promise 但是参数 noop 为空第一类 {} var res = new Promise(noop); // 随即继续执行handle方式 handle(this, new Handler(onFulfilled, onRejected, res)); return res;};

在 then 那个方式中具体来说推论了它是否由 Promise 构造的,如果不是,则返回并继续执行 safeThen ,要不然则继续执行 Promise 构造两个 res 第一类,然后继续执行 handle 方式,最后将 promise 变量 res 返回。 handle 方式之前有提过,在这里,当初始化时 _state 和 _deferred 的转改都为0,因此它会将 defrred 保存到 promise 之中。

先看呵呵上面说的 safeThen 方式

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)); });}

流程

需要有两个 Promise 的构造方式,那个构造方式最终会继续执行它的参数 (resolve, reject) => {} ,声明的 then 方式会透过 handle() 方式将 onFulfilled 和 onRejected 方式保存起来。当在外部调用 resolve 或者 onRejected 时,最终也会继续执行 handle 但是它,会最后根据状况来继续执行 onFulfilled 或者 onRejected 。进而到他们的 then 回调中。

Promise 的扩展

done

对 done 的扩展在 src/done.js 之中

use strict;var Promise = require(./core.js);module.exports = Promise;Promise.prototype.done = function (onFulfilled, onRejected) { var self = arguments.length ? this.then.apply(this, arguments) : this; self.then(null, function (err) { setTimeout(function () { throw err; }, 0); });};

内部继续执行了 then()

finally

对 finally 的扩展在 src/finally.js 之中

在 Promise 的国际标准之中,本身是没有 finally 方式的,但是在 ES2018 的国际标准里有,finally 的同时实现如下

use strict;var Promise = require(./core.js);module.exports = Promise;Promise.prototype.finally = function (callback) { return this.then(function (value) { return Promise.resolve(callback()).then(function () { return value; }); }, function (err) { return Promise.resolve(callback()).then(function () { throw err; }); });};

Promise 的 onFulfilled 和 onRejected 不管回调的哪个,最终都会触发 callback 回调。还要注意的一点是 finally 的返回也是两个 Promise 。

es6-extensions.js

在 es6-extensions.js 文档之中包含了 ES6 的一些扩展。

Promise.resolvefunction valuePromise(value) { var p = new Promise(Promise._noop); // 将_state赋值为 非0 // _value进行保存 p._state = 1; p._value = value; // 这样做的目的是省略的一些前面的逻辑 return p;}Promise.resolve = function (value) { if (value instanceof Promise) return value; if (value === null) return NULL; if (value === undefined) return UNDEFINED; if (value === true) return TRUE; if (value === false) return FALSE; if (value === 0) return ZERO; if (value === ) return EMPTYSTRING; // value return new Promise if (typeof value === object || typeof value === function) { try { var then = value.then; if (typeof then === function) { // 返回 返回了两个新的Promise第一类 return new Promise(then.bind(value)); } } catch (ex) { // 如果收起 则返回两个就只 return new Promise(function (resolve, reject) { reject(ex); }); } } return valuePromise(value);};Promise.rejectPromise.reject = function (value) { return new Promise(function (resolve, reject) { reject(value); });};Promise.allPromise.all = function (arr) { // 类似深拷贝了一份给了args var args = Array.prototype.slice.call(arr); return new Promise(function (resolve, reject) { // 推论了all的promise数量 if (args.length === 0) return resolve([]); // remaining则是promise数组的长度 var remaining = args.length; // i为index val 为 promise function res(i, val) { if (val && (typeof val === object || typeof val === function)) { if (val instanceof Promise && val.then === Promise.prototype.then) { while (val._state === 3) { val = val._value; } if (val._state === 1) return res(i, val._value); if (val._state === 2) reject(val._value); // val._state 为 0时 走这里 val.then(function (val) { res(i, val); }, reject); return; } else { var then = val.then; if (typeof then === function) { var p = new Promise(then.bind(val)); p.then(function (val) { res(i, val); }, reject); return; } } } args[i] = val; // 当所有的promise继续执行完 则是remaining为0 // 则继续执行resolve(); if (–remaining === 0) { resolve(args); } } // 遍历所有的promise for (var i = 0; i < args.length; i++) { res(i, args[i]); } });};

Promise.all() 返回的也是两个 Promise 函数。

内部有两个 remaining 变量每当继续执行完两个 promise 函数后就会减一,当所有 promise 继续执行完,会继续执行自己的 resolve 。

Promise.racePromise.race = function (values) { return new Promise(function (resolve, reject) { values.forEach(function(value){ Promise.resolve(value).then(resolve, reject); }); });};

遍历传入的 promise 数组,经过 Promise.resolve(value) 的源标识符可以看到,如果 value 是两个 Promise 则户直接将那个 value 返回,最后数组中的 promise 哪个优先回调即继续执行。

Promise.property.catch

catch 在国际标准之中也是没有,虽然他们用的比较多

Promise.prototype[catch] = function (onRejected) { return this.then(null, onRejected);};

catch 的回调实际是 then(null, onRejected) 的回调。

举报/反馈

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务