Open Lemonreds opened 6 years ago
此次阅读的 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仓库地址: 链接 原文地址:链接
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 的状态变化,主要有两种情况:
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仓库地址: 链接 原文地址:链接