前言
Promise是什么?
- Promise是ECMA2015规范中推出的,用于异步编程的解决方案,从语法上讲Promise是一个对象,Promise内部可以保存异步操作的结果,创造Promise实例后,它会立即执行。可以通过自身then()方法获取成功或失败的结果。
- Promise为了解决传统异步代码的回调地狱问题,Promise也支持执行多个并发请求时,并在结束后获取执行结果。
一、术语
- promise是具有then方法的对象或函数,其行为符合此规范
- thenable是定义then方法的对象或函数
- value是任意合法的JavaScript值
- exception时使用throw语句抛出的值
- reason是表示promise为什么被rejected的值
// promise的基本示例
const promise = new Promise((resolve, reject) => {
const num = Math.random();
if (num > 0.5) resolve('成功了,当前随机数的值为:' + num);
else reject('失败了,当前随机数的值为:' + num);
});
promise.then(
res => { console.log('promise的状态是成功的,成功的值为' + res) },
err => { console.log('promise的状态是失败的,失败的值为' + err) }
);
二、要求
- promise共三种状态: 请求态(pending) 完成态(fulfilled) 拒绝态(rejected)
- pending状态可以转为fulfilled或rejected
- 状态只能改变一次,已经修改不能再次更改
按照Promise要求定义自己的Promise构造函数和状态
// 为Promise定义常量
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
// 声明构造函数
class MyPromise{
state = PENDING; // 初始化Promise的状态
value = undefined; // Promise状态改为成功时的结果
reason = undefined; // Promise状态改为失败时的结果
constructor(exectuor){
//创建Promise实例时 需调用Promise自身resolve() reject()方法
exectuor(this.resolve.bind(this),this.reject.bind(this))
}
// 实现resolve方法
resolve(value){
// 调用resolve时 更改Promise的状态为fulfilled
// 状态只能更改一次 当状态为初始状态时则更新状态
if(this.state === PENDING){
this.state = FULFILLED;
this.value = value;
}
}
// 实现reject方法
reject(reason){
// 调用reject时 更改Promise的状态为rejected
// 状态只能更改一次 当状态为初始状态时则更新状态
if(this.state === PENDING){
this.state = REJECTED;
this.reason = reason;
}
}
}
小结
- 定义常量保存Promise的三种状态
- 声明Promise的构造函数
- 初始化Promise的状态,成功的结果,失败的结果
- 创建Promise实例时需调用Promise自身的resolve()或reject()方法,更改Promise产生的结果和Promise的状态
三、then方法
- promise必须提供一个then方法来获取其当前或最终的value或reason,pormise的then方法接收两个参数
promise.then(onFulfilled,onRejected)
- onFulfilled和onRejected都是可选参数
2.1. 如果onFulfilled或onRejected不是一个函数,他必须被忽略 - 如果onFulfilled是一个函数
3.1. 它必须在promise被fulfill后调用,promise的value是它的第一个参数。
3.2. 它不能在promise被fulfill前调用。
3.3. 它不能被调用超过一次。 - 如果onRejected是一个函数:
4.1. 它必须在promise被rejected后调用,promise的reason是它的第一个参数。
4.2. 它不能在promise被rejected前调用。
4.3. 它不能被调用超过一次。 - onFulfilled或者onRejected在execution context仅包含平台代码之前不得被调用。
- onFulfilled和onRejected只能被作为函数调用
- 同一promise的then 可以被调用多次。
7.1. 如果/当promise处于fulfilled状态,所有响应的onFulfilled回调必须按它们最初调用then的顺序执行
7.2. 如果/当promise处于rejected状态,所有响应的onRejected回调必须按它们最初调用then的顺序执行 - then必须返回一个promise
8.1. 如果(promise1的)onFulfilled或onRejected之一返回x, 执行Promise解析流程[[Resolve]](promise2, x)
8.2. 如果(promise1的)onFulfilled或onRejected之一抛出一个异常e,promise2 必须以e作为reason被reject
8.3. 如果(promise1的)onFulfilled不是一个函数且promise1变为fulfilled状态,promise2必须以和promise1相同的value被fulfill(大乐注:promise1的onFulfilled被忽略了)
8.4. 如果(promise1的)onRejected不是一个函数且promise1变为rejected状态,promise2必须以和promise1相同的reason被reject(大乐注:promise1的onRejected被忽略了)
按照以上要求实现自己的then方法
class MyPromise {
state = PENDING; // 初始化Promise的状态
value = undefined; // Promise状态改为成功时的结果
reason = undefined; // Promise状态改为失败时的结果
onFulfilledCallbacks = []; // 保存then方法的成功回调
onRejectCallbacks = []; // 保存then方法的失败回调
constructor(exectuor) {
//创建Promise实例时 需调用Promise自身resolve() reject()方法
try {
exectuor(this.resolve.bind(this), this.reject.bind(this));
} catch (error) {
this.reject(error);
}
}
// 实现resolve方法
resolve(value) {
// 调用resolve时 更改Promise的状态为fulfilled
// 状态只能更改一次 当状态为初始状态时则更新状态
if (this.state === PENDING) {
this.state = FULFILLED;
this.value = value;
this.onFulfilledCallbacks.forEach(fn => fn());
}
}
// 实现reject方法
reject(reason) {
// 调用reject时 更改Promise的状态为rejected
// 状态只能更改一次 当状态为初始状态时则更新状态
if (this.state === PENDING) {
this.state = REJECTED;
this.reason = reason;
this.onRejectCallbacks.forEach(fn => fn());
}
}
// 实现then方法
then(onFulfilled, onRejected) {
// 2.1. 如果onFulfilled或onRejected不是一个函数,他必须被忽略
onFulfilled = isFunction(onFulfilled) ? onFulfilled : value => value; // 向下传递value (then方法的穿透)
onRejected = isFunction(onRejected)
? onRejected
: err => {
throw err;
}; // 向下抛出抛出
// then方法支持链式调用 then方法返回的是一个Promise
const promise2 = new MyPromise((resolve, reject) => {
// 它必须在promise被rejected后调用,promise的reason是它的第一个参数
if (this.state === FULFILLED) {
// then方法执行的是一个微任务这里使用queueMicrotask产生一个微任务
queueMicrotask(() => {
if (typeof onFulfilled === 'function') {
try {
// onFulfilled或onRejected之一返回x, 执行Promise解析流程[[Resolve]](promise2, x)
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
// onFulfilled或onRejected之一抛出一个异常e,promise2 必须以e作为reason被reject
reject(error);
}
} else {
// onFulfilled不是一个函数且promise1变为fulfilled状态,promise2必须以和promise1相同的value被fulfill(promise1的onFulfilled被忽略了)
reject(this.value);
}
});
}
// 它必须在promise被rejected后调用,promise的reason是它的第一个参数。
if (this.state === REJECTED) {
// then方法执行的是一个微任务这里使用queueMicrotask产生一个微任务
queueMicrotask(() => {
if (typeof onRejected === 'function') {
try {
// onFulfilled或onRejected之一返回x, 执行Promise解析流程[[Resolve]](promise2, x)
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
// onFulfilled或onRejected之一抛出一个异常e,promise2 必须以e作为reason被reject
reject(error);
}
} else {
// onRejected不是一个函数且promise1变为rejected状态,promise2必须以和promise1相同的reason被reject(promise1的onRejected被忽略了)
reject(this.value);
}
});
}
// 如果调用then时Promise的状态依然为pending,则需要将onFulfilled和onRejected进行管理,并且状态被改变时调用(resolve和reject函数内)
if (this.state === PENDING) {
if (typeof onFulfilled === 'function') {
// 7. 同一promise的then 可以被调用多次。
// promise可以通过then方法调用多次 使用数组管理then方法产生的回调函数
this.onFulfilledCallbacks.push(() => {
queueMicrotask(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
});
}
if (typeof onRejected === 'function') {
// 7. 同一promise的then 可以被调用多次。
// promise可以通过then方法调用多次 使用数组管理then方法产生的回调函数
this.onRejectCallbacks.push(() => {
queueMicrotask(() => {
try {
// onFulfilled或onRejected之一返回x, 执行Promise解析流程[[Resolve]](promise2, x)
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
// onFulfilled或onRejected之一抛出一个异常e,promise2 必须以e作为reason被reject
reject(error);
}
});
});
}
}
});
return promise2;
}
}
小结
- then方法支持链式调用(返回的是一个promise)
- then方法可以调用多次,使用数组去管理onFulfilled和onRejected
- 当onFulfilled或onRejected不是函数时,直接忽略,onFulfilled返回value值,onRejected抛出错误reason
- onFulfilled或onRejected必须在对应状态改变后执行
- 使用queueMicrotask产生一个微任务
- 使用resolvePromise完成Promise的解析流程(下文具体实现)
四、Promise流程解析
- Promise解析流程指接收一个promise和一个任意值x作为输入的一个抽象流程,表示为[[Resolve]](promise, x)。如果x为thenable,它会尝试让promise继承x的状态,前提是x至少行为与promise有一定的相似。否则,它将以x作为value来fulfill这个promise。
- 这种处理thenable的方式允许promise的不同实现互通,只要他们都暴露一个符合Promises/A+规范的then方法。它同时也能支持基于Promises/A+规范的实现与其它不规范但合理的实现(至少带有一个then方法)在一定程度上互相兼容
- [[Resolve]](promise, x)按以下步骤执行:
- 如果promise和x引用同一个对象,以TypeError作为reason来reject这个promise
- 如果x是一个promise,接受它的状态
2.1. 如果x处于pending状态,直到x变为fulfilled或rejected状态,promise必须保持pending状态。
2.2. 如果/当x变为fulfilled状态,以相同的value来fulfill promise
2.3. 如果/当x变为rejected状态,以相同的reason来reject promise - 反之, 如果x是一个object或function
3.1. 如果/当resolvePromise以y作为value被调用, 执行[[Resolve]](promise, y).
3.2. 如果/当rejectPromise以r作为reason被调用, 以r为reason来reject promise.
3.3. 如果resolvePromise和rejectPromise都被调用,或者同一个方法被调用了多次,以第一个调用为准,忽略其余调用
3.4. 如果调用then抛出一个异常e:
3.4.1. 如果resolvePromise已被调用过rejectPromise,忽略异常。
3.4.2. 否则,以e作为reason来reject promise
3.5. 把then设置成x.then
3.6. 如果访问x.then属性导致抛出了一个异常(设为e),以e作为reason来reject promise
3.7. 如果then是一个函数,以x作为this来调用它,并且传入两个参数resolvePromise和rejectPromise
3.8. 如果then不是一个函数,以x作为value来fulfill promise - 如果x不是object或function,将x作为value来fulfill promise。
根据以上规范实现Promise的流程解析 (ResolvePromise)
function resolvePromise(promise, x, resolve, reject) { // 1.如果promise和x引用同一个对象,以TypeError作为reason来reject这个promise if (promise === x) return reject(new TypeError('Chaining cycle detected for promise')); // 2. 如果x是一个promise,接受它的状态 // 3. 反之, 如果x是一个object或function (此处判断包含 条件2 和条件3) let isCalled = false; if (isObject(x) || isFunction(x)) { try { // 3.5. 把then设置成x.then let then = x.then; // 3.7 如果then是一个函数,以x作为this来调用它,并且传入两个参数resolvePromise和rejectPromise if (isFunction(then)) { // 因为存在同名函数 这里使用resolvePromiseThen代替resolvePromise const resolvePromiseThen = y => { // 3.3. 如果resolvePromise和rejectPromise都被调用,或者同一个方法被调用了多次,以第一个调用为准,忽略其余调用 if (isCalled) return; isCalled = true; // 3.1. 如果/当resolvePromise以y作为value被调用, 执行[[Resolve]](promise, y). resolvePromise(promise, y, resolve, reject); }; // 使用rejectPromiseThen代替rejectPromise const rejectPromiseThen = r => { // 3.3. 如果resolvePromise和rejectPromise都被调用,或者同一个方法被调用了多次,以第一个调用为准,忽略其余调用 if (isCalled) return; isCalled = true; reject(r); }; then.call(x, resolvePromiseThen, rejectPromiseThen); } else { // 3.8. 如果then不是一个函数,以x作为value来fulfill promise resolve(x); } } catch (error) { // 3.6. 如果访问x.then属性导致抛出了一个异常(设为e),以e作为reason来reject promise if (isCalled) return; isCalled = true; reject(error); } } else { // 4. 如果x不是object或function,将x作为value来fulfill promise。 resolve(x); } } // 辅助函数 function isPromise(value){ return !!value && (typeof value === "object" || typeof value === "function") && typeof value.then === "function" } function isObject(value){ return !!value && typeof value === 'object' } function isFunction(value){ return !!value && typeof value === 'function' }
小结
- resolvePromise函数用于Promise流程解析,参数为
then函数返回的promise
结果x
resolve()
reject()
- promise和x不能指向同一个引用地址
- x可能是一个promise,是的话根据x的状态执行他或返回对应的结果
- x可能是函数或对象(thenable),取then方法,判断then方法是不是函数
- x作为then方法,以x作为this来调用它,并且传入resolvePromiseThen和rejectPromiseThen方法,获取执行结果
五、catch方法
- catch 方法可以用于您的promise组合中的错误处理
- 当Promise 被rejected时,被调用的一个Function。 该函数拥有一个参数:reason rejection 的原因。
- 如果 onRejected 抛出一个错误或返回一个本身失败的 Promise , 通过 catch() 返回的Promise 被rejected;否则,它将显示为成功(resolved)。
1. 使用示例
const promise = new Promise((resolve, reject) => {
reject('错误的结果');
});
promise.then().catch(err => {
console.log('err', err);
});
2. 实现过程
/**
* catch方法
* 内部直接调用then方法 将回调函数传递到onRejected
*/
catch(onRejected) {
return this.then(undefined, onRejected);
}
六、finally方法
- 方法返回一个Promise。无论结果promise的执行结果是fulfilled或rejected,都会执行指定的回调函数。
- 需要执行上一次promise的执行结果,方便在下一次then()方法中获取finally上层then返回的结果
1. 使用示例
const promise = new Promise((resolve,reject)=>{
resolve('成功')
})
promise.then(res=>{
throw new Error('返回第一个错误')
}).finally(()=>{
console.log('成功或失败都会执行')
}).then(()=>{},err=>{
// 获取第一个then返回的错误结果
console.log('err',err)
throw new Error('返回第二个错误')
}).catch((err)=>{
// 获取第二个错误结果
console.log('catch',err)
})
2. 实现过程
finally(onFinally) {
// 返回一个promise
return new Promise((resolve, reject) => {
// 判断上一个promise的状态
console.log(this.state);
if (this.state === FULFILLED) {
queueMicrotask(() => {
try {
onFinally();
resolve(this.value);
} catch (error) {
reject(error);
}
});
}
if (this.state === REJECTED) {
queueMicrotask(() => {
try {
onFinally();
resolve(this.reason);
} catch (error) {
reject(error);
}
});
}
if (this.state === PENDING) {
this.onFulfilledCallbacks.push(() => {
queueMicrotask(() => {
try {
onFinally();
resolve(this.state === FULFILLED ? this.value : this.reason);
} catch (error) {
reject(error);
}
});
});
}
});
}
七、静态resolve()
- 直接调用Promise.resolve方法.并产生一个成功的结果
- value可能存在的情况
- 普通值和空值 - 使用resolve返回当前值
- 是一个Promise实例 - 直接返回此结果
- thenable对象
1. 使用示例
MyPromise.resolve(MyPromise.resolve(MyPromise.resolve('成功了')))
.then(res => {
console.log(res);
})
2. 实现过程
static resolve(value) {
// 是一个Promise实例 - 直接返回此promise
if(value instanceof MyPromise) return value;
// 返回一个新的promise
return new MyPromise((resolve,reject)=>{
// thenable对象调用自身then方法
if(value && value.then && typeof value.then === 'function'){
value.then(resolve,reject);
}
else resolve(value);
})
}
八、静态reject()
- 直接调用Promise.reject方法.并产生一个失败的结果
1. 使用示例
MyPromise.reject('失败了')
.catch(err => {
console.log(err);
})
2. 实现过程
static reject(value) {
// 返回一个新的promise
return new MyPromise((_,reject)=>{
reject(value);
})
}
九、all()
- 接收一个可迭代的集合对象(实现了iterable),并返回一个Promise实例
- 当前所有结果全部返回成功时,返回成功结果组成的数组
- 当任何一个promise执行失败时,返回第一个执行失败的结果
1. 使用示例
const p1 = Promise.resolve('成功1')
const p2 = Promise.resolve('成功2')
const p3 = new Promise((resolve,reject)=>{ setTimeout(()=>{ reject('失败3') },1000) })
Promise.all([p1,p2,p3])
.then(err => {
console.log(err);
}).catch(err=>{
console.log(err)
})
2. 实现过程
static all(promises) {
return new MyPromise((resolve, reject) => {
let result = []; // 返回的结果数组
let index = 0; //计数器 全部执行完毕返回成功的结果
let promise = null;
for (let i = 0; i < promises.length; i++) {
promise = promises[i];
// 是Promise 则执行then方法并将结果保存到结果数组
if (isPromise(promise)) {
promise.then(data => {
result[i] = data;
if (++index === promises.length) resolve(result);
}, reject);
} else {
// 非promise 直接将当前值存入结果数组
result[i] = promise;
}
}
});
}
十、allSettled()
- 接收一个可迭代的集合对象(实现了iterable),全部执行完毕后返回一个Promise实例
- 返回多个对象组成的数组,通过status判断promise的执行状态
- 当任何一个promise执行失败时,返回第一个执行失败的结果
1. 使用示例
const p1 = Promise.resolve('成功1')
const p2 = Promise.resolve('成功2')
const p3 = new Promise((resolve,reject)=>{ setTimeout(()=>{ reject('失败3') },1000) })
Promise.all([p1,p2,p3])
.then(err => {
console.log(err);
}).catch(err=>{
console.log(err)
})
2. 实现过程
static allSettled(promises) {
return new MyPromise((resolve, reject) => {
let result = []; // 返回的结果数组
let index = 0; //计数器 全部执行完毕返回成功的结果
let promise = null;
for (let i = 0; i < promises.length; i++) {
promise = promises[i];
// 是Promise 则执行then方法并将结果保存到结果数组
if (isPromise(promise)) {
promise.then(
data => {
result[i] = { status: FULFILLED, value: data };
if (++index === promises.length) resolve(result);
},
reason => {
result[i] = { status: REJECTED, reason: reason };
if (++index === promises.length) resolve(result);
}
);
} else {
// 非promise 直接将当前值存入结果数组
result[i] = promise;
}
}
});
}
十一、race()
- 接收一个可迭代的集合对象(实现了iterable),并返回一个Promise
- 一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝 (哪个执行的速度快,返回哪个)
- 如果传递的可迭代集合是空的,那么返回的promise状态为pending
1. 使用示例
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('失败1');
}, 2000);
});
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('失败2');
}, 1000);
});
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('失败3');
}, 3000);
});
Promise.race([p1, p2, p3])
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err);
});
2. 实现过程
static race(promises) {
return new MyPromise((resolve, reject) => {
for (let promise of promises) {
if (isPromise(promise)) {
console.log(promise.state);
// 根据promise的状态返回对应的结果
if (promise.state === PENDING) {
promise.then(resolve, reject);
}
if (promise.state === FULFILLED) {
promise.then(resolve);
}
if (promise.state === REJECTED) {
promise.then(undefined, reject);
}
} else {
reject(promise);
}
}
});
}
十二、Promise完整代码
// 辅助函数
function isPromise(value) {
return !!value && (typeof value === 'object' || typeof value === 'function') && typeof value.then === 'function';
}
function isObject(value) {
return !!value && typeof value === 'object';
}
function isFunction(value) {
return !!value && typeof value === 'function';
}
function resolvePromise(promise, x, resolve, reject) {
// 1.如果promise和x引用同一个对象,以TypeError作为reason来reject这个promise
if (promise === x) return reject(new TypeError('Chaining cycle detected for promise'));
// 2. 如果x是一个promise,接受它的状态
// 3. 反之, 如果x是一个object或function (此处判断包含 条件2 和条件3)
let isCalled = false; // 此变量用于判断同一个方法是否调用多次
if (isObject(x) || isFunction(x)) {
try {
// 3.5. 把then设置成x.then
let then = x.then;
if (isFunction(then)) {
// 因为存在同名函数 这里使用resolvePromiseThen代替resolvePromise
const resolvePromiseThen = y => {
// 3.3. 如果resolvePromise和rejectPromise都被调用,或者同一个方法被调用了多次,以第一个调用为准,忽略其余调用
if (isCalled) return;
isCalled = true;
// 3.1. 如果/当resolvePromise以y作为value被调用, 执行[[Resolve]](promise, y).
resolvePromise(promise, y, resolve, reject);
};
// 使用rejectPromiseThen代替rejectPromise
const rejectPromiseThen = r => {
// 3.3. 如果resolvePromise和rejectPromise都被调用,或者同一个方法被调用了多次,以第一个调用为准,忽略其余调用
if (isCalled) return;
isCalled = true;
reject(r);
};
// 3.7 如果then是一个函数,以x作为this来调用它,并且传入两个参数resolvePromise和rejectPromise
then.call(x, resolvePromiseThen, rejectPromiseThen);
} else {
// 3.8. 如果then不是一个函数,以x作为value来fulfill promise
resolve(x); // 此时x是普通值 直接返回结果
}
} catch (error) {
// 3.6. 如果访问x.then属性导致抛出了一个异常(设为e),以e作为reason来reject promise
if (isCalled) return;
isCalled = true;
reject(error);
}
} else {
// 4. 如果x不是object或function,将x作为value来fulfill promise。
resolve(x);
}
}
// 为Promise定义常量
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
// 声明构造函数
class MyPromise {
state = PENDING; // 初始化Promise的状态
value = undefined; // Promise状态改为成功时的结果
reason = undefined; // Promise状态改为失败时的结果
onFulfilledCallbacks = []; // 保存then方法的成功回调
onRejectCallbacks = []; // 保存then方法的失败回调
constructor(exectuor) {
//创建Promise实例时 需调用Promise自身resolve() reject()方法
try {
exectuor(this.resolve.bind(this), this.reject.bind(this));
} catch (error) {
this.reject(error);
}
}
// 实现resolve方法
resolve(value) {
// 调用resolve时 更改Promise的状态为fulfilled
// 状态只能更改一次 当状态为初始状态时则更新状态
if (this.state === PENDING) {
this.state = FULFILLED;
this.value = value;
this.onFulfilledCallbacks.forEach(fn => fn());
}
}
// 实现reject方法
reject(reason) {
// 调用reject时 更改Promise的状态为rejected
// 状态只能更改一次 当状态为初始状态时则更新状态
if (this.state === PENDING) {
this.state = REJECTED;
this.reason = reason;
this.onRejectCallbacks.forEach(fn => fn());
}
}
// 实现then方法
// 2. onFulfilled和onRejected都是可选参数
then(onFulfilled, onRejected) {
// 2.1. 如果onFulfilled或onRejected不是一个函数,他必须被忽略
onFulfilled = isFunction(onFulfilled) ? onFulfilled : value => value; // 向下传递value (then方法的穿透)
onRejected = isFunction(onRejected)
? onRejected
: err => {
throw err;
}; // 向下抛出抛出
// then方法支持链式调用 then方法返回的是一个Promise
const promise2 = new MyPromise((resolve, reject) => {
// 它必须在promise被rejected后调用,promise的reason是它的第一个参数
if (this.state === FULFILLED) {
// then方法执行的是一个微任务这里使用queueMicrotask产生一个微任务
queueMicrotask(() => {
if (typeof onFulfilled === 'function') {
try {
// onFulfilled或onRejected之一返回x, 执行Promise解析流程[[Resolve]](promise2, x)
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
// onFulfilled或onRejected之一抛出一个异常e,promise2 必须以e作为reason被reject
reject(error);
}
} else {
// onFulfilled不是一个函数且promise1变为fulfilled状态,promise2必须以和promise1相同的value被fulfill(promise1的onFulfilled被忽略了)
reject(this.value);
}
});
}
// 它必须在promise被rejected后调用,promise的reason是它的第一个参数。
if (this.state === REJECTED) {
// then方法执行的是一个微任务这里使用queueMicrotask产生一个微任务
queueMicrotask(() => {
if (typeof onRejected === 'function') {
try {
// onFulfilled或onRejected之一返回x, 执行Promise解析流程[[Resolve]](promise2, x)
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
// onFulfilled或onRejected之一抛出一个异常e,promise2 必须以e作为reason被reject
reject(error);
}
} else {
// onRejected不是一个函数且promise1变为rejected状态,promise2必须以和promise1相同的reason被reject(promise1的onRejected被忽略了)
reject(this.value);
}
});
}
// 如果调用then时Promise的状态依然为pending,则需要将onFulfilled和onRejected进行管理,并且状态被改变时调用(resolve和reject函数内)
if (this.state === PENDING) {
if (typeof onFulfilled === 'function') {
// 7. 同一promise的then 可以被调用多次。
// promise可以通过then方法调用多次 使用数组管理then方法产生的回调函数
this.onFulfilledCallbacks.push(() => {
queueMicrotask(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
});
}
if (typeof onRejected === 'function') {
// 7. 同一promise的then 可以被调用多次。
// promise可以通过then方法调用多次 使用数组管理then方法产生的回调函数
this.onRejectCallbacks.push(() => {
queueMicrotask(() => {
try {
// onFulfilled或onRejected之一返回x, 执行Promise解析流程[[Resolve]](promise2, x)
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
// onFulfilled或onRejected之一抛出一个异常e,promise2 必须以e作为reason被reject
reject(error);
}
});
});
}
}
});
return promise2;
}
/**
* catch方法
* 内部直接调用then方法 将回调函数传递到onRejected
*/
catch(onRejected) {
return this.then(undefined, onRejected);
}
/**
* finaly方法
* 无论Promise的结果为成功或者失败 都会走到finally中,并将之前的结果原封不动的返回到下一次then中
*/
finally(onFinally) {
// 返回一个promise
return new MyPromise((resolve, reject) => {
// 判断上一个promise的状态
if (this.state === FULFILLED) {
queueMicrotask(() => {
try {
onFinally();
resolve(this.value);
} catch (error) {
reject(error);
}
});
}
if (this.state === REJECTED) {
queueMicrotask(() => {
try {
onFinally();
resolve(this.reason);
} catch (error) {
reject(error);
}
});
}
if (this.state === PENDING) {
this.onFulfilledCallbacks.push(() => {
queueMicrotask(() => {
try {
onFinally();
resolve(this.state === FULFILLED ? this.value : this.reason);
} catch (error) {
reject(error);
}
});
});
}
});
}
/**
* 静态resolve()
* 返回一个新的promise对象
* 可以直接使用构造函数调用此方法,并产生一个成功的结果
*/
static resolve(value) {
if (value instanceof MyPromise) return value;
// 返回一个新的promise
return new MyPromise((resolve, reject) => {
// 可能是thenable
if (value && value.then && typeof value.then === 'function') {
value.then(resolve, reject);
} else resolve(value);
});
}
/**
* 静态reject方法
*/
static reject(value) {
// 返回一个新的promise
return new MyPromise((_, reject) => {
reject(value);
});
}
/**
* all方法
* 接收一个可迭代的集合对象(实现了iterable),并返回一个Promise
* 当前所有结果全部返回成功时,返回成功结果组成的数组
* 当任何一个promise执行失败时,返回第一个执行失败的结果
* 集合内的元素是promise时,执行promise.then()方法,否则直接返回这个元素
*/
static all(promises) {
return new MyPromise((resolve, reject) => {
let result = []; // 返回的结果数组
let index = 0; //计数器 全部执行完毕返回成功的结果
let promise = null;
for (let i = 0; i < promises.length; i++) {
promise = promises[i];
// 是Promise 则执行then方法并将结果保存到结果数组
if (isPromise(promise)) {
promise.then(data => {
result[i] = data;
if (++index === promises.length) resolve(result);
}, reject);
} else {
// 非promise 直接将当前值存入结果数组
result[i] = promise;
}
}
});
}
/**
* allSelled
* 接收一个可迭代的集合对象(实现了iterable),并返回一个Promise
* 返回多个对象组成的数组,通过status判断promise的执行状态
*/
static allSettled(promises) {
return new MyPromise((resolve, reject) => {
let result = []; // 返回的结果数组
let index = 0; //计数器 全部执行完毕返回成功的结果
let promise = null;
for (let i = 0; i < promises.length; i++) {
promise = promises[i];
// 是Promise 则执行then方法并将结果保存到结果数组
if (isPromise(promise)) {
promise.then(
data => {
result[i] = { status: FULFILLED, value: data };
if (++index === promises.length) resolve(result);
},
reason => {
result[i] = { status: REJECTED, reason: reason };
if (++index === promises.length) resolve(result);
}
);
} else {
// 非promise 直接将当前值存入结果数组
result[i] = promise;
}
}
});
}
/**
* race
* 接收一个可迭代的集合对象(实现了iterable),并返回一个Promise
* 一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝 (哪个执行的速度快,返回哪个)
* 如果传递的可迭代集合是空的,那么返回的promise状态为pending
*/
static race(promises) {
return new MyPromise((resolve, reject) => {
for (let promise of promises) {
if (isPromise(promise)) {
// 根据promise的状态返回对应的结果
if (promise.state === PENDING) {
promise.then(resolve, reject);
}
if (promise.state === FULFILLED) {
promise.then(resolve);
}
if (promise.state === REJECTED) {
promise.then(undefined, reject);
}
} else {
reject(promise);
}
}
});
}
}
/**
* 测试Promise程序
* yarn add promises-aplus-tests
* npx promises-aplus-tests promise.js(当前文件名)
*/
MyPromise.defer = MyPromise.deferred = function() {
let dfd = {};
dfd.promise = new MyPromise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
};
module.exports = MyPromise;