promise 源码 | 根据promiseA+规范手写自己的promise
手写 promise
Promise 规范官网 promisesaplus.com/
GitHub github.com/Dklns/Pract…
完成一个基本的 Promise 类
-
总代码
// 定义三种状态的常量 const PENDING = 'PENDING'; const FULFILLED = 'FULFILLED'; const REJECT = 'REJECT'; class MyPromise { /* 构造函数 参数为一个回调函数,在构造函数中传入定义好的两个回调函数 ———— resolve 和reject 两个回调函数的作用是,改变 promise 对象的状态和携带的值 */ constructor(executor) { this.status = PENDING; this.value = undefined; this.reason = undefined; const resolve = value => { if (this.status == PENDING) { this.value = value; this.status = FULFILLED; } } const reject = reason => { if (this.status == PENDING) { this.reason = reason; this.status = REJECT; } } // 必须捕获错误,因为 executor 回调函数抛出错误 算 reject try { executor(resolve, reject); } catch (error) { reject(error); } } /* then方法有两个参数,成功和失败的回调 当状态改变时,执行对应的回调 */ then(onFulfilled, onRejected) { if (this.status == FULFILLED) { onFulfilled(this.value); } if (this.status == REJECT) { onRejected(this.reason); } } } module.exports = MyPromise;
为基础 Promise 类添加 then 的异步处理
-
总代码
// 定义三种状态的常量 const PENDING = 'PENDING'; const FULFILLED = 'FULFILLED'; const REJECT = 'REJECT'; class MyPromise { /* 构造函数 参数为一个回调函数,在构造函数中传入定义好的两个回调函数 ———— resolve 和reject 两个回调函数的作用是,改变 promise 对象的状态和携带的值 */ constructor(executor) { this.status = PENDING; this.value = undefined; this.reason = undefined; this.fulfilledCBQueue = []; // 成功回调队列 this.rejectedCBQueue = []; // 失败回调队列 const resolve = value => { if (this.status == PENDING) { this.value = value; this.status = FULFILLED; // 执行由 then 方法推入回调队列中的回调 this.fulfilledCBQueue.forEach(cb => cb()); } } const reject = reason => { if (this.status == PENDING) { this.reason = reason; this.status = REJECT; this.rejectedCBQueue.forEach(cb => cb()); } } // 必须捕获错误,因为 executor 回调函数抛出错误 算 reject try { executor(resolve, reject); } catch (error) { reject(error); } } /* then方法有两个参数,成功和失败的回调 当状态改变时,执行对应的回调 */ then(onFulfilled, onRejected) { if (this.status == FULFILLED) { onFulfilled(this.value); } if (this.status == REJECT) { onRejected(this.reason); } /* 当 executor 函数内存在异步时,由于then 是同步执行的,即在 new Promise() 后 promise.then() 那么 promise.status 是异步更改的,那么在 then 内读取到的状态就是 PENDING */ if (this.status == PENDING) { this.fulfilledCBQueue.push(() => { onFulfilled(this.value); }); this.rejectedCBQueue.push(() => { onRejected(this.reason); }); } } } module.exports = MyPromise; -
变化代码
constructor(executor) { // ..... **this.fulfilledCBQueue = []; // 成功回调队列 this.rejectedCBQueue = []; // 失败回调队列** const resolve = value => { if (this.status == PENDING) { this.value = value; this.status = FULFILLED; // 执行由 then 方法推入回调队列中的回调 **this.fulfilledCBQueue.forEach(cb => cb());** } } const reject = reason => { if (this.status == PENDING) { this.reason = reason; this.status = REJECT; **this.rejectedCBQueue.forEach(cb => cb());** } } } // ........... then(onFulfilled, onRejected) { // ............ /* 当 executor 函数内存在异步时,由于then 是同步执行的,即在 new Promise() 后 promise.then() 那么 promise.status 是异步更改的,那么在 then 内读取到的状态就是 PENDING */ **if (this.status == PENDING) { this.fulfilledCBQueue.push(() => { onFulfilled(this.value); }); this.rejectedCBQueue.push(() => { onRejected(this.reason); }); }** }
实现 Promise.then() 的链式调用
链式调用的核心就是 then 方法返回 新的 Promise
const promise1 = new Promise((resolve, reject) => {
resolve("first resolve");
})
const promise2 = promise1.then(res => res);
promise2.then(res => console.log(res)); // first resolve
promise2 能成功调用 then 方法说明,promise.then() 方法一定返回一个 promise对象
promise 规范
thenmust return a promise
then 返回新的 promise 对象
那么下面对 then 方法进行一个初步的更改
then(onFulfilled, onRejected) {
// 创建新的promise 对象
const promise2 = new Promise((resolve, reject) => {
if (this.status == FULFILLED) {
onFulfilled(this.value);
}
if (this.status == REJECT) {
onReject(this.reason);
}
if (this.status == PENDING) {
this.fulfilledCBQueue.push(() => {
onFulfilled(this.value);
});
this.rejectedCBQueue.push(() => {
onReject(this.reason);
});
}
})
// 返回新的 promise 对象
return promise2;
}
将原来的 onFulfilled 和 onRejected 执行的操作放入 新的 promise 的 executor 中
**resolvePromise 方法**
接着看文档
- If either
onFulfilledoronRejectedreturns a valuex, run the Promise Resolution Procedure[[Resolve]](promise2, x).
onFulfilled onRejected 的返回结果 用变量 x 保存
// 返回新的promise对象
promise.then(value => {
return new Promise((resolve, reject) => {
resolve('resolve');
})
})
// 返回字符串
promise.then(value => {
return 'resolve';
})
那么 x 的值就有那种可能,一是普通值,二是 promise 对象。对于onFulfilled 返回的 promise 对象而言,我们需要的实际是它携带的 value,然后赋给 promise2
因此就需要 有一个 [[Resolve]] 来处理这个问题
then 回调执行中发生错误则返回的 promise 对象为 rejected
在此之前,先来解决另一个问题
let promise2 = promise.then(value => {
throw new Error('error');
return new Promise((resolve, reject) => {
resolve('resolve');
})
})
promise2.then(null, err => console.log(err)) // error
在 then 方法中执行回调发生错误的话,返回的 promise 对象就是 拒绝状态,并且 reason 就是报错内容
所以下面代码用 try catch 包裹上了每个回调执行过程
-
代码
then(onFulfilled, onRejected) { // 创建新的promise 对象 const promise2 = new Promise((resolve, reject) => { if (this.status == FULFILLED) { try { // 用 try catch 包裹每一个回调的执行 let x = onFulfilled(this.value); } catch (error) { reject(error); } } if (this.status == REJECT) { try { let x = onRejected(this.reason); } catch (error) { reject(error); } } if (this.status == PENDING) { this.fulfilledCBQueue.push(() => { try { let x = onFulfilled(this.value); } catch (error) { reject(error); } }); this.rejectedCBQueue.push(() => { try { let x = onRejected(this.reason); } catch (error) { reject(error); } }); } }) // 返回新的 promise 对象 return promise2; }
引出resolvePromise()
[[resolve]] 即resolvePromise 方法,根据 x 的值决定 then 返回的 promise2对象的状态。所以这个方法肯定需要传参 → 需返回的 promise2 的 resolve 和 reject 回调,因为这两个回调才能更改 promise2 的状态
- If
promiseandxrefer to the same object, rejectpromisewith aTypeErroras the reason.
根据这条规范还可以得知,resolvePromise 内部还需要判断 promise 和 x 是否一致
所以 resolvePromise 的调用应如下
//---------------
let x = onRejected(this.reason);
resolvePromise(promise2,x ,resolve ,reject);
//---------------
但是仅仅只是下面这样(假设 resolvePromise 已定义),是会报错的,因为 promise2 此时为 undefined 而 executor 却尝试使用promise2
//----------------------
const **promise2** = new Promise((resolve, reject) => {
if (this.status == FULFILLED) {
try {
let x = onFulfilled(this.value);
resolvePromise(**promise2**,x ,resolve ,reject);
} catch (error) {
reject(error);
}
}
//--------------------
}
onFulfilledoronRejectedmust not be called until the execution context stack contains only platform code.
- Here “platform code” means engine, environment, and promise implementation code. In practice, this requirement ensures that
onFulfilledandonRejectedexecute asynchronously, after the event loop turn in whichthenis called, and with a fresh stack. This can be implemented with either a “macro-task” mechanism such assetTimeoutorsetImmediate, or with a “micro-task” mechanism such asMutationObserverorprocess.nextTick. Since the promise implementation is considered platform code, it may itself contain a task-scheduling queue or “trampoline” in which the handlers are called.
再根据这些规范可以得知,我们应该使用 setTimeout 或者 setImmediate 将 onFulfilled onRejected 改为异步执行
//---------------------------------------
const promise2 = new Promise((resolve, reject) => {
if (this.status == FULFILLED) {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2,x ,resolve ,reject);
} catch (error) {
reject(error);
}
}, 0);
}
//-------------------------------------------
}
这样做的话,executor 内部就能使用 promise2 了,同时 onFulfilled onRejected 的执行也是异步的,不会造成阻塞问题
**resolvePromise 的实现**
经过上面的分析,处理链式调用的核心就转移到了 resolvePromise 方法上了
现在我们根据规范编写代码
- If
promiseandxrefer to the same object, rejectpromisewith aTypeErroras the reason.
以下代码会触发这种情况
const promise = new Promise((resole, reject) => {
resole(1);
});
let promise2 = promise.then(res => {
return promise2;
})
// [TypeError:Chaining cycle detected for promise #<Promise>]
所以第一步代码为
function resolvePromise(promise2, x, resolve, reject) {
if(promise2 === x) {
// 警告信息直接复制官方的
return reject(new TypeError("Chaining cycle detected for promise #<MyPromise>"));
}
}
**resolvePromise方法的实现过程规范**
- If
xis a promise, adopt its state [3.4]:
- If
xis pending,promisemust remain pending untilxis fulfilled or rejected.- If/when
xis fulfilled, fulfillpromisewith the same value.- If/when
xis rejected, rejectpromisewith the same reason.- Otherwise, if
xis an object or function,
- Let
thenbex.then. [3.5]- If retrieving the property
x.thenresults in a thrown exceptione, rejectpromisewitheas the reason.- If
thenis a function, call it withxasthis, first argumentresolvePromise, and second argumentrejectPromise, where:
- If/when
resolvePromiseis called with a valuey, run[[Resolve]](promise, y).- If/when
rejectPromiseis called with a reasonr, rejectpromisewithr.- If both
resolvePromiseandrejectPromiseare called, or multiple calls to the same argument are made, the first call takes precedence, and any further calls are ignored.- If calling
thenthrows an exceptione,
- If
resolvePromiseorrejectPromisehave been called, ignore it.- Otherwise, reject
promisewitheas the reason.- If
thenis not a function, fulfillpromisewithx.- If
xis not an object or function, fulfillpromisewithx
然后是判断 x 的类型,如果 x 是对象或者 函数则判断是否有 then 属性,否则 x 就是普通值,直接 调用promise2 的 resolve 即可
接着判断 then 属性是否为 函数,如果是则以 x 为 this 使用 call 方法调用,onfulfilled 和 onRejected 的参数为y 和 r 。然后分别调用 promise 的 resolve 和 reject ,这样做就可以既改变 promise2 的状态,又拿到 x 的 value 或者 reason
需要注意的是,如果这个 x.then 的 get 有故意阻塞代码的话,代码就会出错,所以需要用 try catch 包裹 x.then 的访问,并用 reject 处理 error
if (typeof x === 'object' && x != null || typeof x === 'function') {
try {
let then = x.then;
if (typeof then === 'function') {
then.call(x, (y) => {
resolve(y);
}, (r) => {
reject(r);
});
} else {
resolve(x);
}
} catch (error) {
reject(error);
}
} else {
resolve(x);
}
⚠️ 待补充解释,关于规范 If both `resolvePromise` and `rejectPromise` are called, or multiple calls to the same argument are made, the first call takes precedence, and any further calls are ignored. 的代码补充
我不理解为什么要这样优化
-
代码
**let called = false;** if (typeof x === 'object' && x != null || typeof x === 'function') { try { let then = x.then; if (typeof then === 'function') { then.call(x, (y) => { **if(called) return; called = true;** resolve(y); }, (r) => { **if(called) return; called = true;** reject(r); }); } else { resolve(x); } } catch (error) { **if(called) return; called = true;** reject(error); } } else { resolve(x); }
优化
⚠️ 我自己在实现的过程中,发现我的代码不需要以下优化也能正常运行,很奇怪
if (typeof x === 'object' && x != null || typeof x === 'function') {
try {
let then = x.then;
if (typeof then === 'function') {
then.call(x, (y) => {
if (called) return;
called = true;
// 递归调用 resolePromise ,因为如果 y 是 promise 对象,直接使用 promise2
// 的resolve 处理 y 的话,也不过是把 y 赋给 promise.value
**resolvePromise(promise2, y, resolve, reject);**
}, (r) => {
if (called) return;
called = true;
// 而 reject 不需要递归,因为 r 是错误信息
reject(r);
});
} else {
resolve(x);
}
} catch (error) {
if (called) return;
called = true;
reject(error);
}
} else {
resolve(x);
}
给 onFulfilled onRejected 设置默认值
promise.then().then().then(res => console.log(res), reason => console.log(reason));
如果仅是上边的代码那么这样链式调用,就会报错 undefined is not a function
需要注意的是,onRejected 的默认值是直接抛出错误,这样在链式调用中,只要不给 onRejected 赋值,最终程序就会报错,除非 onRejected 被赋值,其实际意义就是用户主动处理 reject 状态
then(onFulfilled, onRejected) {
**onFulfilled = onFulfilled ? onFulfilled : val => val;
onRejected = onRejected ? onRejected : reason => { throw reason };**
//--------------------
}
优化 resolve 回调
用现在的 MyPromise 执行下面的代码得不到真正的 value,打印出来的是 pending 态的 promise
const promise = new MyPromise((resolve, reject) => {
resolve(new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('second');
}, 2000)
}));
});
promise.then(val => {
console.log(val);
})
因为 resolve 回调不过是简单地赋值,根本没有判断 value 是否为 promise 类型
const resolve = value => {
if (this.status == PENDING) {
this.value = value;
this.status = FULFILLED;
// 执行由 then 方法推入回调队列中的回调
this.fulfilledCBQueue.forEach(cb => cb());
}
}
优化
const resolve = value => {
**if(value instanceof MyPromise) {
value.then(resolve , reject);
return; // 一定要 return,不然会无限递归
}**
if (this.status == PENDING) {
this.value = value;
this.status = FULFILLED;
// 执行由 then 方法推入回调队列中的回调
this.fulfilledCBQueue.forEach(cb => cb());
}
}
catch
catch 实际上就是 then 的语法糖
catch(errorCallback) {
return this.then(null, errorCallback);
}
实现 resolve 与 reject 的静态方法
官方的 resolve reject 静态方法的表现实际上就是
resolve(value) ,如果 value 是普通值,就直接赋给返回的 promise 对象,而如果 value instanceof Promise,则取得其携带的 value ,然后赋给返回的 promise 对象
reject(reason),reason 无论是普通值还是 promise 对象,都赋值给返回的失败态 promise
Promise.resolve(new Promise((resolve, reject) => {
resolve('klns')
})).then(val => {
console.log(val); // klns
})
Promise.reject(new Promise((resolve, reject) => {
resolve('llxs');
})).then(null, reason => {
console.log(reason); // Promise { 'llxs' }
})
优化
所以就是一个语法糖,分别用 resolve 和 reject 回调去处理 value 和 reason 就行了
static resolve(value) {
return new Promise((resolve, reject) => {
resolve(value);
})
}
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason);
})
}
实现Promise.all()
Promise.all() 返回一个 promise,当参数数组内所有 promise 都为成功态时,这个promise 才为成功态,然后promise 携带的 value 为参数数组内 所有 value(普通值就是普通值,promise就是携带的 value) 的数组
一旦有一个 promise 为失败态,返回的 promsie 就转为失败态
const fs = require('fs');
function readFile(path) {
return new Promise((resolve, reject) => {
fs.readFile(path, 'utf-8', function (err, data) {
if (err) {
reject(err);
}
resolve(data);
})
})
}
Promise.all(
[
1,
readFile('./text/example1.txt'),
readFile('./text/example2.txt')
])
.then(val => {
console.log(val); // [ 1 , 'this is example1' , 'this is example2']
}, reason => {
console.log(reason);
})
-
总代码
static all(promiseArr) { let valueArr = []; // 存放所有 value 的数组 let promiseArrLength = promiseArr.length; let storedValueNum = 0; // 记录以及存入 valueArr 的 promise.value 的数量 if (promiseArrLength === 0) { // 当参数为空数组时 return MyPromise.resolve([]); } return new MyPromise((resolve, reject) => { promiseArr.forEach((promise, idx) => { if (isPromise(promise)) { // 如果是 promise 对象就调用其 then 拿出value promise.then(val => { putInValueArr(val, idx, resolve); }, reject); } else { // 如果为普通值则直接存入数组 putInValueArr(promise, idx, resolve); } }) // 把 promise.value 放入 valueArr中,且改变需返回 promise 的状态 function putInValueArr(val, idx, resolve) { valueArr[idx] = val; if (++storedValueNum === promiseArrLength) { resolve(valueArr); } } // 判断是否为 promise 对象 function isPromise(promise) { if (typeof promise === 'object' && promise != null || typeof promise === 'function') { let then = promise.then; return typeof then === 'function'; } return false; } }) }
那么这个方法一定得返回一个新的 promise 对象,并且需要一个数组保存所有的 value
**static all(promiseArr) {
let valueArr = [];
return new MyPromise((resolve, reject) => {
});
}**
然后遍历 promiseArr 数组,并判断 item 的类型,这里可以把判断过程抽离出来
static all(promiseArr) {
let valueArr = [];
return new MyPromise((resolve, reject) => {
**promiseArr.forEach((promise, idx) => {
if(isPromise(promise)) {
} else {
}
})**
});
**function isPromise(promise) {
if(typeof promise === 'object' && promise != null || typeof promise === 'function') {
let then = promise.then;
return typeof then === 'function';
}
return false;
}**
}
那么接下来就是拿到每个 promise 的 value,并将其放入 valueArr 中。同时记录已经放入的 value 的个数,因为当已经放入的个数等于所有 promise 的个数即 promiseArr.length 时,全部 promise 就已经成功了
想要取到 promise 的 value 只可能调用 promise.then(),而 then 内的回调是只有 promise 状态改变后才会执行的,所有存入操作在 then 内回调中,这样就可以配合记录数实现”全部 promise 成功态,返回 promise 才转为成功态,一旦有失败态,其转为失败态“
static all(promiseArr) {
if (!isIterable(promiseArr)) { // 判断是否可迭代
throw new TypeError(`object ${promiseArr} is not iterable (cannot read property Symbol(Symbol.iterator))`)
}
let valueArr = [];
let storedValueNum = 0;
let promiseArrLength = promiseArr.length;
if (promiseArrLength === 0) { // 当参数为空数组时
return MyPromise.resolve([]);
}
return new MyPromise((resolve, reject) => {
promiseArr.forEach((promise, idx) => {
if (isPromise(promise)) {
promise.then(value => {
putInValueArr(value, idx, resolve);
}, reject);
} else {
putInValueArr(promise, idx, resolve);
}
})
});
function putInValueArr(value, idx, resolve) {
valueArr[idx] = value;
if (++storedValueNum === promiseArrLength) {
resolve(valueArr);
}
}
}
function isPromise(promise) {
if (typeof promise === 'object' && promise != null || typeof promise === 'function') {
let then = promise.then;
return typeof then === 'function';
}
return false;
}
function isIterable(value) {
if (value !== null && value !== undefined
&& typeof value[Symbol.iterator] === 'function') {
return true;
}
return false;
}
但是现在的 all 还不够健壮
当 promiseArr 长度为零时应返回以空数组为 value 的成功态 promise
当 参数不可迭代时,应抛出错误
static all(promiseArr) {
**if (!isIterable(promiseArr)) { // 判断是否可迭代
throw new TypeError(`object ${promiseArr} is not iterable (cannot read property Symbol(Symbol.iterator))`)
}**
let valueArr = [];
let storedValueNum = 0;
let promiseArrLength = promiseArr.length;
**if (promiseArrLength === 0) { // 当参数为空数组时
return MyPromise.resolve([]);
}**
//...........................
}
**function isIterable(value) {
if (value !== null && value !== undefined
&& typeof value[Symbol.iterator] === 'function') {
return true;
}
return false;
}**
实现 promise.allSettled
promise.allSettled 的结果是 value 是一个数组的 promise对象,数组成员是包含两个属性的对象
{
status,
value/reason
}
这个方法与 promise.all 的区别就在于,无论参数数组中的 promise 是否成功都将其放入 valueArr中,并按照特定的对象形式
那么这个方法相比较 promise.all 就是 putInValueArr 函数需要修改
static allSettled(promiseArr) {
if (!isIterable(promiseArr)) { // 判断是否可迭代
throw new TypeError(`object ${promiseArr} is not iterable (cannot read property Symbol(Symbol.iterator))`)
}
let valueArr = [];
let storedValueNum = 0;
let promiseArrLength = promiseArr.length;
if (promiseArrLength === 0) { // 当参数为空数组时
return MyPromise.resolve([]);
}
return new MyPromise((resolve, reject) => {
promiseArr.forEach((promise, idx) => {
if (isPromise(promise)) {
promise.then(value => {
putInValueArr('fulfilled', value, idx, resolve);
}, reason => {
putInValueArr('rejected', reason, idx, resolve);
});
} else {
putInValueArr('fulfilled', promise, idx, resolve);
}
})
function putInValueArr(status, value, idx, resolve) {
switch (status) {
case 'fulfilled': {
valueArr[idx] = {
status,
value
}
};
case 'rejected': {
valueArr[idx] = {
status,
reason: value
}
};
break;
}
if (++storedValueNum === promiseArrLength) {
resolve(valueArr);
}
}
})
}
实现 promise.race
promise.race 要实现的功能就是遍历给出的参数数组中的成员,将其或其携带的 value 或 reason 给需返回的 promise 的 value 或 reason
也就是说在从参数数组中第一个开始,谁最先执行完,就会是 race (竞赛) 的冠军
static race(promiseArr) {
if (!isIterable(promiseArr)) { // 判断是否可迭代
throw new TypeError(`object ${promiseArr} is not iterable (cannot read property Symbol(Symbol.iterator))`)
}
if (promiseArr.length === 0) { // 当参数为空数组时
return MyPromise.resolve([]);
}
return new MyPromise((resolve, reject) => {
promiseArr.forEach(promise => {
if (isPromise(promise)) {
promise.then(value => {
resolve(value);
}, reason => {
reject(reason);
})
} else {
resolve(promise);
}
})
})
}
实现 promise.finnally
(这里信息是指 value 或者 reason)
promise.finnally 表现出的特点如下:
- 上层
promise失败,内部回调失败,信息为内部回调返回信息 - 上层
promise成功,内部回调失败,信息为内部回调返回信息 - 上层
promise成功,内部回调成功,信息为上层信息 - 上层
promise失败,内部回调成功,信息为上层信息 promise.finnally的回调函数没有参数,且一条promise链一定会等待这个回调函数执行完
MyPromise.reject('rejected').finally(() => {
return MyPromise.reject('new Rejected');
}).then(value => {
console.log(value);
}, reason => {
console.log(reason);
}); // new Rejected
MyPromise.resolve('fulfilled').finally(() => {
return MyPromise.reject('new Rejected');
}).then(value => {
console.log(value);
}, reason => {
console.log(reason);
}); // new Rejected
MyPromise.resolve('fulfilled').finally(() => {
return MyPromise.resolve('new fulfilled');
}).then(value => {
console.log(value);
}, reason => {
console.log(reason);
}); // fulfilled
MyPromise.reject('rejected').finally(() => {
return MyPromise.resolve('new fulfilled');
}).then(value => {
console.log(value);
}, reason => {
console.log(reason);
}); // rejected
首先 promise.finnally 的回调函数没有参数,但是又需要上层 promise 的信息。promise.finnally 是一个原型方法,其的调用肯定是实例,那么方法内的 this 就是指向上层 promise ,所以通过 this.then() 就可以取到信息了
finally(finallyCB) {
this.then(value => {
}, reason => {
});
}
下一个需求就是 promise 链的后续操作需要等待 finnallyCB 执行完成,那么就需要用 新的 promise 包裹 finnallyCB,并将 this.then 的返回 promise 作为 finnally 的返回 promise
finally(finallyCB) {
**return** this.then(value => {
**return MyPromise.resolve(finallyCB);**
}, reason => {
**return MyPromise.resolve(finallyCB);**
});
}
接着就是前四点特点
简而言之就是需要根据上层 promise 的状态和 finnallyCB 可能的状态决定最终返回 promise 的状态和所携带信息
finally(finallyCB) {
return this.then(value => {
return MyPromise.resolve(finallyCB)**.then(() => value**);
}, reason => {
return MyPromise.resolve(finallyCB)**.then(() => {
throw reason;
});**
});
}
用 A 代表上层 promise,用 B 代表 MyPromise.resolve(finallyCB)
当 A 成功时,会走 A 的 onFulfilled。如果 B 成功的话会走 B 的 onFulfilled 但是返回的 value 是 A 的value;如果 B 失败,会走 B 的 onRejected。
当 A 失败时,会走 A 的 onRejected。如果 B 成功的话会走 B 的 onFulfilled 但是抛出 A 的 reason;如果 B 失败的话,则 走 B 的 onRejected。
转载自:https://juejin.cn/post/7206239276895780925