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 实现是 ES6-Promise ,是 promise 的众多实现中较为完善的一个例子,从入口文件 lib/es6-promise/promise.js 开始阅读,可以看到 Promise 定义有如下的静态方法
Promise.all Promise.race Promise.resolve Promise.reject
以及挂载在 Promise.protoype 上的方法
Promise.prototype.then Promise.prototype.catch Promise.prototype.finally
接下来会对其核心代码进行解读。
Promise规范中定义了promise的三种状态,而且promise的状态更新只能是以下两种情况,一旦状态发生改变之后就不能再修改:
ES6-Promise 内部中的定义如下:
// void 运算符 对表达式进行求值,结果都返回 undefined // 可以防止undefined被重写,如:const undefined = xxx const PENDING = void 0; // undefined const FULFILLED = 1; const REJECTED = 2;
我们来看一个Promise的使用例子,传入一个函数即resolver,初始化一个promise实例。函数会被立即执行,并且可以使用promise传入的两个参数 resolve 和 reject ,resolve 和 reject都是函数,都接收一个参数, value 或者 reason,在resolver函数内部调用 resolve 或者 reject ,都会更新promise的状态 。
具体调用例子如:
const promise = new Promise(function(resolve, reject) { if (/* 异步操作成功 */){ // 更新状态为 fulfilled 并缓存 value resolve(value); } else { // 更新状态为 rejected 并缓存 reason reject(error); } });
为了响应promise不同的状态(fulfilled 或 rejected),可以通过实例的 then 方法绑定回调函数:
promise.then( // resolver 中 resolve 的 value value => { /* pending -> fulfilled 时调用 */ }, // resolver 中 reject 的 resaon reason => { /* pending -> rejected 时调用 */ } )
这样就完成了一个promise的基本使用。
接下来我们先看看promise的构造方法:
class Promise { constructor(resolver) { // nextId() 返回一个自增的闭包变量 作为Promise实例的唯一标识 this[PROMISE_ID] = nextId(); // _result 缓存 resolve 时的 value 或者 reject 时的 reason // _state 缓存 promise 的当前状态 this._result = this._state = undefined; // 订阅序列 this._subscribers = []; // noop = ()=>{} 内部定义的一个空函数 // 内部调用时: new Promise(noop) 不会经过下面的初始化过程 // 外部调用时: 对传入参数进行检查 if (noop !== resolver) { // 条件1:resolver 必须要是一个函数 typeof resolver !== 'function' && needsResolver(); // 条件2: 必须通过 new Promise() 初始化实例 this instanceof Promise ? initializePromise(this, resolver) : needsNew(); } }
可以看到promise的构造方法完成了以下的工作:
初始化变量,包括 该实例独一无二的ID,用于缓存value或者reason的 _result,用于订阅promise状态变化的序列 _subscriber(后面会讲到)
对入参 resolver 进行判断 resolver === noop noop是内部定义的一个空函数,此时 promise 会初始化结束。 resolver !== noop resolver 必须是函数,同时必须是通过 new Promise() 初始化实例。 满足以上两个条件的,就会调用 initializePromise方法,对实例进一步加工,其代码如下:
function initializePromise(promise, resolver) { try { // 立即执行 resolver函数 resolver(function resolvePromise(value) { resolve(promise, value); }, function rejectPromise(reason) { reject(promise, reason); }); } catch (e) { // 代码发生异常 // 则直接更新 promise 的状态为 rejected reject(promise, e); } }
可以看到,resolver函数被立即执行了,同时给函数传参 resolvePromise 和 rejectPromise ,它们包装了内部实现的 resolve 和 reject 函数。
再来看看内部的 resolve和 reject 是如何对promise状态进行更新的。
reject函数较为简单:
/** * pending => rejected */ function reject(promise, reason) { // 状态一旦改变就不可逆转 if (promise._state !== PENDING) { return; } // 缓存处理结果 更新promise状态 promise._state = REJECTED; promise._result = reason; // asap(func,param) 暂不详细解释 可以理解为立即执行 func(param) // promise 的状态发生了改变 通知订阅者 asap(publishRejection, promise); }
promise的状态更新为rejected后,会通过publishRejection向订阅序列发出通知,publishRejection函数代码如下,具体的publish函数封装了如何向订阅序列发出通知的逻辑,后续会说到:
function publishRejection(promise) { //这 个onError 好像一直都是null啊 if (promise._onerror) { promise._onerror(promise._result); } // 向订阅序列发出通知 publish(promise); }
resolve 则会对 value 的类型进行判断,然后分步操作,情况有以下:
具体代码逻辑如下:
function resolve(promise, value) { if (promise === value) { // 1. 不允许 value 是 promise实例本身 // 更新为 rejected 状态 reject(promise, selfFulfillment()); } else if (objectOrFunction(value)) { // 2. value是对象或者函数 handleMaybeThenable(promise, value, getThen(value)); } else { // 3. 其他数据类型 fulfill(promise, value); } }
先看第三种判断 fulfill 方法,方法不难理解,就是更新promise的状态为 fulfilled 同时向订阅序列发出通知。
/** * pedding => fulfilled */ function fulfill(promise, value) { // promise状态不可逆 if (promise._state !== PENDING) { return; } // 缓存处理结果和promise状态 promise._result = value; promise._state = FULFILLED; // 向订阅序列发出通知 if (promise._subscribers.length !== 0) { asap(publish, promise); } }
再来看看第二种判断,当 resolve 函数传入的value是对象或者函数,调用特殊处理的 handleMaybeThenable(promise,value,getThen(value))方法。
其中getThen方法接收一个参数promise,用于尝试获取promise的then属性,会捕获错误,返回包装的错误对象。
虽然知道了value是对象或者函数value是对象或者函数,但函数内部又对value进行了进一步划分。
handleMaybeThenable的具体代码如下:
function handleMaybeThenable(promise, maybeThenable, then) { if ( maybeThenable.constructor === promise.constructor && then === originalThen && maybeThenable.constructor.resolve === originalResolve) { // 1. resolve的值是一个 promise 实例 // 即通过 new Promise() 新建的实例 handleOwnThenable(promise, maybeThenable); } else { // 2. 获取 value 的 then 属性错误 // 更新 promise 的 状态为 rejected if (then === TRY_CATCH_ERROR) { reject(promise, TRY_CATCH_ERROR.error); TRY_CATCH_ERROR.error = null; } else if (then === undefined) { // 3. 不存在 then 属性 // 按照普通数据类型进行处理 fulfill(promise, maybeThenable); } else if (isFunction(then)) { // 4. resolve的值是一个 thenable 对象, 具有then属性,并且为函数 handleForeignThenable(promise, maybeThenable, then); } else { // 5. then 是其他数据类型 直接进行处理 fulfill(promise, maybeThenable); } } }
总结一下 resolve 的值分为以下情况:
第一种情况中,handleOwnThenable 具体代码如下:
/** * resolve 的值 value 是一个 promise 实例 * @param promise 当前的promise * @param thenable value */ function handleOwnThenable(promise, thenable) { // 检查 thenable 状态 if (thenable._state === FULFILLED) { // FULFILLED 状态 // 使用 thenable 内部缓存的处理结果 // 作为 value 调用 fulfill 更新状态 fulfill(promise, thenable._result); } else if (thenable._state === REJECTED) { // REJECTED 状态 // 使用 thenable 内部缓存的处理结果 // 作为 reason 调用 reject 更新状态 reject(promise, thenable._result); } else { // pending 状态, 对 thenable 增加监听 // 当 thenable 的状态改变时 // 用其结果缓存 更新 promise 的状态 subscribe(thenable, undefined, value => resolve(promise, value), reason => reject(promise, reason)) } }
也就是说,当resolve的value是一个promise时,原封不动地返回这个promise,可以理解为使用此promise进行链式传递了。
第二种情况,当为一个具有then属性并且then为函数的对象时:
// let thenable = { // then: function(resolve, reject) { // resolve(42); // } // }; function handleForeignThenable(promise, thenable, then) { asap(promise => { // 用一个 sealed 保证只能调用一次 var sealed = false; // tryThen 方法 // 1. 以 thenable 作为执行上下文 // 2. 传入 (value=>{} , reason=>{}) 参数 // 3. 执行 then 函数 var error = tryThen(then, thenable, value => { if (sealed) { return; } sealed = true; if (thenable !== value) { // 如果 resolve 的 value 不是原来的thenale对象 // 进一步对value进行处理(有可能又是一个promise实例或者thenable对象,或者其他情况...) resolve(promise, value); } else { // 如果 resolve 的 value 还是原来的thenale对象 // 则直接 fulfill 这个对象 // 不再进一步通过 resolve 避免死循环 fulfill(promise, value); } }, reason => { if (sealed) { return; } sealed = true; // then 方法 reject(‘xx') reject(promise, reason); }, 'Settle: ' + (promise._label || ' unknown promise')); // if error // rejected 状态 if (!sealed && error) { sealed = true; reject(promise, error); } }, promise); }
也就是说,当resolve的值是一个thenable对象时,会执行其then方法,根据then方法中调用入参resolve或者reject时传入的value或reason来对promise的状态进行更新。
之前有提到promise的订阅,在Promise初始化的时候,声明了一个内部变量,用来存储对promise的订阅序列。
// 订阅序列 this._subscribers = [];
然后可以调用 subscribe 函数注册监听:
/** * @param {promise} parent 被订阅状态变化的Promise * @param {promise} child 订阅状态变化的Promise(可为undefined) * @param {function} onFulfillment 状态变化为 fulfilled 的订阅函数 * @param {function} onRejection 状态变化为 rejected 的订阅函数 */ function subscribe(parent, child, onFulfillment, onRejection) { let { _subscribers } = parent; let { length } = _subscribers; parent._onerror = null; // 每调用一次subscribe函数 订阅序列会增加三个元素 _subscribers[length] = child; _subscribers[length + FULFILLED] = onFulfillment; _subscribers[length + REJECTED] = onRejection; // 有可能是在 parent 状态更新之后增加的订阅 // 此时的订阅序列被清空 状态不再发生变化 则直接发出通知 if (length === 0 && parent._state) { asap(publish, parent); } }
可以看到,对一个promise订阅其状态更新时,会在其订阅序列增加三个参数,子promise(可为空),状态变为fulfilled时的回调,变为rejected时的回调。 当一个promise状态更新之后,就会触发publish函数,发布修改,触发相应状态的回调,publish的具体代码逻辑如下:
/** * Promise状态更新 发出通知 * @param {Promise} promise */ function publish(promise) { // 所有订阅序列 let subscribers = promise._subscribers; // promise的状态 let settled = promise._state; // 订阅序列为空 if (subscribers.length === 0) { return; } /** * child: 订阅状态变化的promise * callback: 回调函数 * detail: value或者reason缓存 */ let child, callback, detail = promise._result; // 每三个元素为一个订阅单位 格式如: child + fufilled + rejected for (let i = 0; i < subscribers.length; i += 3) { // child === [object Promise] child = subscribers[i]; // 根据 promsie 的状态获取相应的回调函数 callback = subscribers[i + settled]; // 情况1: 存在promise实例订阅 if (child) { invokeCallback(settled, child, callback, detail); } else { // 情况2: 触发响应的回调函数 callback(detail); } } // 清空监听数组 promise._subscribers.length = 0; }
每三个元素为一个单位,publish函数会依次判断订阅者:
第一种情况下:
/** * settled : 被监听promise的状态 * promise : 订阅监听的promise * callback : fullfled | rejected * detial : value | reason */ function invokeCallback(settled, promise, callback, detail) { let hasCallback = isFunction(callback), value, error, succeeded, failed; if (hasCallback) { // 尝试执行回调函数 // 发生错误时 则返回 TRY_CATCH_ERROR 对象 value = tryCatch(callback, detail); // 执行cb函数时出错 if (value === TRY_CATCH_ERROR) { // 获取error的值 failed = true; error = value.error; value.error = null; } else { // 设置状态 succeeded = true; } // 不允许回调函数返回了原有的promise实例 if (promise === value) { reject(promise, cannotReturnOwn()); return; } } else { // 不存在回调函数 value = detail; succeeded = true; } // 更新 promise 的状态 if (promise._state !== PENDING) { // noop } else if (hasCallback && succeeded) { // 回调函数存在的情况 // value 是回调函数的返回值 resolve(promise, value); } else if (failed) { // error 是调用回调函数的错误时的原因 reject(promise, error); } else if (settled === FULFILLED) { // 回调函数不存在的情况 // 直接使用父promise的value fulfill(promise, value); } else if (settled === REJECTED) { reject(promise, value); } }
总结一下,订阅一个promise 的状态变化,主要有两种情况:
方法传入两个函数参数,当promise的状态更新后,调用相应的回调函数,同时返回一个新的promise。
export default function then(onFulfillment, onRejection) { // 当前的 promise const parent = this; // 新建一个 promise // new pormise(()=>{}) // [!] 通过此方式创建的 promise 不会进行 initializePromise 方法初始化 // initializePromise 会执行传入的函数 空函数不需要执行 只需要初始化相关变量 const child = new this.constructor(noop); // 仅初始化状态变量 // promise[PROMISE_ID] = id++; // promise._state = undefined; // promise._result = undefined; // promise._subscribers = []; if (child[PROMISE_ID] === undefined) { makePromise(child); } // 获取当前 promise 的状态 const { _state } = parent; // 当前的 promise 为 fullfied / rejected // 直接处理 if (_state) { // state = fullfied ===> onFulfillment // state = rejected ===> onRejection // 获取与状态对应的处理函数 const callback = arguments[_state - 1]; // 传入结果立即执行 // 更新新建promise的状态 asap(() => invokeCallback(_state, child, callback, parent._result)); } else { // 当前的 promise 为 pending // 将新建的 promise 绑定在 当前 promise 上 // 当前的 pormise 状态改变之后 同步新建的 promise 状态 subscribe(parent, child, onFulfillment, onRejection); } // 返回新建的 promise return child; }
总结一下,首先 then 方法会返回一个新的promise,其状态和原来的 promise 同步,结果缓存则有以下的两种情况。
也就是下面的两种例子:
// 1. 第一种情况 let promise = new Promise((resolve,reject)=>{ resolve('OK') }) let child1 = promise.then((value)=>{ return value + 'child1' },()=>{}) // 此时child1的结果缓存是 'OKchild1' // 2. 第二种情况 let child2 = promise.then().then().then().then().then( value =>{ console.log(value) // 结果缓存还是最开始那个promise 也就是 'OK' })
catch方法是then方法的语法糖,通常我们会这样设置回调:
let promise = new Promise((resolve,reject)=>{ if(/* 异步OK*/){ resolve('OK') }else{ reject(new Error('something wrong')) } }).then(value=>{ // xxx }).catch(err=>{ // xxx }) // 但实际上等同于 promise.then( value=>{},err=>{})
其代码也很简单:
/** * Promise.prototype.catch */ catch (onRejection) { return this.then(null, onRejection); }
finally方法用于无论状态发生了什么改变(fulfilled或者rejected)都要执行的操作,来自ES2018的标准。 注意:代码中的Promise.resolve 可先看看下面关于此方法的解读。
/** * Promise.prototype.finally */ finally(callback) { // 当前 promise let promise = this; // Promise let constructor = promise.constructor; if (isFunction(callback)) { // Promise.resolve 包裹成一个promise //再调用其 then 方法返回一个新的promise 链式传递vakue/reason return promise.then( // pending -> fulfilled value => constructor.resolve(callback()).then(() => value), // pending -> rejected reason => constructor.resolve(callback()).then(() => { throw reason; })); } // callback 不是函数 return promise.then(callback, callback); }
方法接收一个参数,返回一个Promise,可接受的输入情况有:
// 1. 传入的是一个 promise实例 // 直接返回这个实例 Promise.resolve(promise); // 2. 传入的是一个 thenable实例 // 执行 thenable 的 then 方法 // 根据 方法内部 resolve 或者 reject 得到的 value 或者 resaon // 设置为 promise 的状态和结果缓存 let thenable = { then: function(resolve, reject) { resolve(42); } }; Promise.resolve(theanable); // 3. 普通数据值 返回一个 fulfilled 状态的 promise // 结果缓存为其 value Promise.resolve(value);
具体代码实现如下
export default function resolve(object) { // Promise.resolve = Resolve; // [ Promise ] let Constructor = this; // 1. 传入一个 promise 实例 // 则直接返回这个promise if (object && typeof object === 'object' && object.constructor === Constructor) { return object; } // 新建一个空的 promise // 不会经过 initialPromise() 方法的初始化 let promise = new Constructor(noop); // 2. 可能是 thenable 对象 // 或者是其他普通值 _resolve(promise, object); // 返回 promise return promise; }
方法较为简单,接收一个参数reason,直接返回一个状态为rejected的promise实例。
export default function reject(reason) { // Promise.reject // Promise let Constructor = this; // new Promise(()=>{}) // 不会经过 initialPromise() 方法的初始化 let promise = new Constructor(noop); // pending -> rejected _reject(promise, reason); // 返回promise return promise; }
方法传入一个 数组,一般传入多个promise,包装成一个promise返回,这个promise的状态和传入的多个promise中最先更新状态那一个promise同步。
export default function race(entries) { // Promise let Constructor = this; if (!isArray(entries)) { // 不是数组 返回一个状态为rejected的Promise实例 return new Constructor((_, reject) => reject(new TypeError('You must pass an array to race.'))); } else { // 返回一个新的 Promise 实例 return new Constructor((resolve, reject) => { let length = entries.length; for (let i = 0; i < length; i++) { // Promise.resolve(entries[i]).then(resolve,reject) // 遍历所有元素 用 Promise.resolve() 包装成 Promise实例 // 最先的一个 Promise 更新了状态后 都会同步外层 Promise Constructor.resolve(entries[i]).then(resolve, reject); } }); } }
方法也是传入一个数组,一般传入多个promise,包装成一个promise返回,其状态有以下两种情况: 1 : 所有promise的状态都变成fulfilled时,返回的promise状态为fulfilled,结果是所有promise返回值的数组 2 : 有一个promise的状态率先变为rejected,返回的promise状态为rejected,结果是这个promise rejected的返回值
代码如下:
// Promise.all export default function all(entries) { // 初始化一个 Enumerator 实例 返回其属性 promise return new Enumerator(this, entries).promise; }
Enumerator的具体代码如下:
export default class Enumerator { constructor(Constructor, input) { // Promise this._instanceConstructor = Constructor; // 新建一个空的promise 不会经过 initialPromise() 方法的初始化 // Promise.all() 最后返回这个值 this.promise = new Constructor(noop); // 初始化 // promise[PROMISE_ID] = id++; // promise._state = undefined; // promise._result = undefined; // promise._subscribers = []; if (!this.promise[PROMISE_ID]) { makePromise(this.promise); } if (isArray(input)) { // 总长度 this.length = input.length; // 剩余长度 this._remaining = input.length; // 存放结果 this._result = new Array(this.length); if (this.length === 0) { // 空数组 // 返回一个状态为 fulfilled 的promise fulfill(this.promise, this._result); } else { this.length = this.length || 0; // 执行 _enumerate this._enumerate(input); if (this._remaining === 0) { // 剩余长度为0 // 返回一个状态为 fulfilled 的promise fulfill(this.promise, this._result); } } } else { // 入参不是数组 // 返回一个状态为r ejected 的promise reject(this.promise, validationError()); } } _enumerate(input) { // 遍历执行所有状态为 pending 的 promise for (let i = 0; this._state === PENDING && i < input.length; i++) { this._eachEntry(input[i], i); } } _eachEntry(entry, i) { // Promise.all() 方法 传入的是 Promise let c = this._instanceConstructor; // Promise.resolve let { resolve } = c; // Promise.resolve = Promise.resolve if (resolve === originalResolve) { // 尝试获取 entry 的 then 属性 let then = getThen(entry); if (then === originalThen && entry._state !== PENDING) { // then === Promise.prototype.then // 情况1: entry是promise实例 同时 状态不为 pending this._settledAt(entry._state, i, entry._result); } else if (typeof then !== 'function') { // then 不为函数 为普通值 // 直接设置 this._remaining--; this._result[i] = entry; } else if (c === Promise) {// true 在Promise.all() 中此处一直成立 let promise = new c(noop); // then 是一个函数 // 对 then 进行进一步检查 如果是一个 thenable 对象 // let thenable = { // then: function(resolve,reject)=>{ resolve('66')} // } // 则会执行 then 方法 获取相应的值后设置 promise 的状态 handleMaybeThenable(promise, entry, then); // 设置监听 this._willSettleAt(promise, i); } else { // 情况2: entry是promise实例 状态为 pending // 绑定监听 待entry状态改变之后 再设置相应的值 this._willSettleAt(new c(resolve => resolve(entry)), i); } } else { // 其他情况 这里不作考虑 // 因为�Promise.all 传入的是Promise this._willSettleAt(resolve(entry), i); } } _settledAt(state, i, value) { let { promise } = this; if (promise._state === PENDING) { // 又完成了一个 Promise this._remaining--; if (state === REJECTED) { // 一旦有一个promise实例状态变为rejected // 更新状态为rejected reject(promise, value); } else {// fulfilled // 更新值 this._result[i] = value; } } if (this._remaining === 0) { // 所有的元素都已经变为 fulfilled // 同步返回promise的状态 fulfill(promise, this._result); } } _willSettleAt(promise, i) { let enumerator = this; // 绑定监听 // promise的状态改变后 调用相应的函数 subscribe( promise, undefined, value => enumerator._settledAt(FULFILLED, i, value), reason => enumerator._settledAt(REJECTED, i, reason) ); } };
以上便是es6-promise核心代码的阅读。
ES6-Promise仓库地址: 链接 原文地址:链接
The text was updated successfully, but these errors were encountered:
No branches or pull requests
ES6-Promise 源码阅读
前言
此次阅读的 promise 实现是 ES6-Promise ,是 promise 的众多实现中较为完善的一个例子,从入口文件 lib/es6-promise/promise.js 开始阅读,可以看到 Promise 定义有如下的静态方法
Promise.all
Promise.race
Promise.resolve
Promise.reject
以及挂载在 Promise.protoype 上的方法
Promise.prototype.then
Promise.prototype.catch
Promise.prototype.finally
接下来会对其核心代码进行解读。
Promise的三种状态
Promise规范中定义了promise的三种状态,而且promise的状态更新只能是以下两种情况,一旦状态发生改变之后就不能再修改:
ES6-Promise 内部中的定义如下:
Promise的使用例子
我们来看一个Promise的使用例子,传入一个函数即resolver,初始化一个promise实例。函数会被立即执行,并且可以使用promise传入的两个参数 resolve 和 reject ,resolve 和 reject都是函数,都接收一个参数, value 或者 reason,在resolver函数内部调用 resolve 或者 reject ,都会更新promise的状态 。
具体调用例子如:
为了响应promise不同的状态(fulfilled 或 rejected),可以通过实例的 then 方法绑定回调函数:
这样就完成了一个promise的基本使用。
Promise的构造函数
接下来我们先看看promise的构造方法:
可以看到promise的构造方法完成了以下的工作:
初始化变量,包括 该实例独一无二的ID,用于缓存value或者reason的 _result,用于订阅promise状态变化的序列 _subscriber(后面会讲到)
对入参 resolver 进行判断
resolver === noop noop是内部定义的一个空函数,此时 promise 会初始化结束。
resolver !== noop resolver 必须是函数,同时必须是通过 new Promise() 初始化实例。
满足以上两个条件的,就会调用 initializePromise方法,对实例进一步加工,其代码如下:
可以看到,resolver函数被立即执行了,同时给函数传参 resolvePromise 和 rejectPromise ,它们包装了内部实现的 resolve 和 reject 函数。
再来看看内部的 resolve和 reject 是如何对promise状态进行更新的。
内部的 reject 函数
reject函数较为简单:
promise的状态更新为rejected后,会通过publishRejection向订阅序列发出通知,publishRejection函数代码如下,具体的publish函数封装了如何向订阅序列发出通知的逻辑,后续会说到:
内部的 resolve 函数
resolve 则会对 value 的类型进行判断,然后分步操作,情况有以下:
具体代码逻辑如下:
先看第三种判断 fulfill 方法,方法不难理解,就是更新promise的状态为 fulfilled 同时向订阅序列发出通知。
再来看看第二种判断,当 resolve 函数传入的value是对象或者函数,调用特殊处理的 handleMaybeThenable(promise,value,getThen(value))方法。
其中getThen方法接收一个参数promise,用于尝试获取promise的then属性,会捕获错误,返回包装的错误对象。
虽然知道了value是对象或者函数value是对象或者函数,但函数内部又对value进行了进一步划分。
handleMaybeThenable的具体代码如下:
总结一下 resolve 的值分为以下情况:
第一种情况中,handleOwnThenable 具体代码如下:
也就是说,当resolve的value是一个promise时,原封不动地返回这个promise,可以理解为使用此promise进行链式传递了。
第二种情况,当为一个具有then属性并且then为函数的对象时:
也就是说,当resolve的值是一个thenable对象时,会执行其then方法,根据then方法中调用入参resolve或者reject时传入的value或reason来对promise的状态进行更新。
subscribe 订阅机制
之前有提到promise的订阅,在Promise初始化的时候,声明了一个内部变量,用来存储对promise的订阅序列。
然后可以调用 subscribe 函数注册监听:
可以看到,对一个promise订阅其状态更新时,会在其订阅序列增加三个参数,子promise(可为空),状态变为fulfilled时的回调,变为rejected时的回调。
当一个promise状态更新之后,就会触发publish函数,发布修改,触发相应状态的回调,publish的具体代码逻辑如下:
每三个元素为一个单位,publish函数会依次判断订阅者:
第一种情况下:
总结一下,订阅一个promise 的状态变化,主要有两种情况:
有回调函数的话,传入value或者reason到相应的回调函数执行,回调函数的返回值作为结果缓存到子promise。
无回调函数的话,就直接使用value或者reason作为结果缓存。
Promise.prototype.then
方法传入两个函数参数,当promise的状态更新后,调用相应的回调函数,同时返回一个新的promise。
总结一下,首先 then 方法会返回一个新的promise,其状态和原来的 promise 同步,结果缓存则有以下的两种情况。
也就是下面的两种例子:
Promise.protoype.catch
catch方法是then方法的语法糖,通常我们会这样设置回调:
其代码也很简单:
Promise.prototype.finally
finally方法用于无论状态发生了什么改变(fulfilled或者rejected)都要执行的操作,来自ES2018的标准。
注意:代码中的Promise.resolve 可先看看下面关于此方法的解读。
Promise.resolve
方法接收一个参数,返回一个Promise,可接受的输入情况有:
具体代码实现如下
Promise.reject
方法较为简单,接收一个参数reason,直接返回一个状态为rejected的promise实例。
Promise.race
方法传入一个 数组,一般传入多个promise,包装成一个promise返回,这个promise的状态和传入的多个promise中最先更新状态那一个promise同步。
Promise.all
方法也是传入一个数组,一般传入多个promise,包装成一个promise返回,其状态有以下两种情况:
1 : 所有promise的状态都变成fulfilled时,返回的promise状态为fulfilled,结果是所有promise返回值的数组
2 : 有一个promise的状态率先变为rejected,返回的promise状态为rejected,结果是这个promise rejected的返回值
代码如下:
Enumerator的具体代码如下:
以上便是es6-promise核心代码的阅读。
最后
ES6-Promise仓库地址: 链接
原文地址:链接
The text was updated successfully, but these errors were encountered: