根据PromiseA+规范从零实现Promise【这一次,带你彻底搞懂Promise使用和原理】

本文深入浅出地讲解了Promise的原理和使用,按照PromiseA+规范逐步实现Promise构造函数、then方法、catch方法、finally方法等核心功能,旨在帮助读者彻底理解Promise的工作机制和应用技巧。

前言

Promise是什么?

1.Promise是ECMA2015规范中推出的,用于异步编程的解决方案,从语法上讲Promise是一个对象,Promise内部可以保存异步操作的结果,创造Promise实例后,它会立即执行。可以通过自身then()方法获取成功或失败的结果。
2.Promise为了解决传统异步代码的回调地狱问题,Promise也支持执行多个并发请求时,并在结束后获取执行结果。

一、术语

1.promise是具有then方法的对象或函数,其行为符合此规范
2.thenable是定义then方法的对象或函数
3.value是任意合法的JavaScript值
4.exception时使用throw语句抛出的值
5.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) }
); 

二、要求

1.promise共三种状态: 请求态(pending) 完成态(fulfilled) 拒绝态(rejected)
2.pending状态可以转为fulfilled或rejected
3.状态只能改变一次,已经修改不能再次更改

按照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方法

1.promise必须提供一个then方法来获取其当前或最终的value或reason,pormise的then方法接收两个参数> promise.then(onFulfilled,onRejected)2.onFulfilled和onRejected都是可选参数 2.1. 如果onFulfilled或onRejected不是一个函数,他必须被忽略
3.如果onFulfilled是一个函数 3.1. 它必须在promise被fulfill后调用,promise的value是它的第一个参数。 3.2. 它不能在promise被fulfill前调用。 3.3. 它不能被调用超过一次。
4.如果onRejected是一个函数: 4.1. 它必须在promise被rejected后调用,promise的reason是它的第一个参数。 4.2. 它不能在promise被rejected前调用。 4.3. 它不能被调用超过一次。
5.onFulfilled或者onRejected在execution context仅包含平台代码之前不得被调用。
6.onFulfilled和onRejected只能被作为函数调用
7.同一promise的then 可以被调用多次。 7.1. 如果/当promise处于fulfilled状态,所有响应的onFulfilled回调必须按它们最初调用then的顺序执行 7.2. 如果/当promise处于rejected状态,所有响应的onRejected回调必须按它们最初调用then的顺序执行
8.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方法返回的是一个Promiseconst 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被rejectreject(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被rejectreject(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被rejectreject(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)按以下步骤执行:1.如果promise和x引用同一个对象,以TypeError作为reason来reject这个promise2.如果x是一个promise,接受它的状态 2.1. 如果x处于pending状态,直到x变为fulfilled或rejected状态,promise必须保持pending状态。 2.2. 如果/当x变为fulfilled状态,以相同的value来fulfill promise 2.3. 如果/当x变为rejected状态,以相同的reason来reject promise3.反之, 如果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 promise4.如果x不是object或function,将x作为value来fulfill promise。### 根据以上规范实现Promise的流程解析 (ResolvePromise)function resolvePromise(promise, x, resolve, reject) {// 1.如果promise和x引用同一个对象,以TypeError作为reason来reject这个promiseif (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.thenlet then = x.then;// 3.7 如果then是一个函数,以x作为this来调用它,并且传入两个参数resolvePromise和rejectPromiseif (isFunction(then)) {// 因为存在同名函数 这里使用resolvePromiseThen代替resolvePromiseconst 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代替rejectPromiseconst 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 promiseresolve(x);}} catch (error) {// 3.6. 如果访问x.then属性导致抛出了一个异常(设为e),以e作为reason来reject promiseif (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方法

1.catch 方法可以用于您的promise组合中的错误处理
2.当Promise 被rejected时,被调用的一个Function。 该函数拥有一个参数:reason rejection 的原因。
3.如果 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方法

1.方法返回一个Promise。无论结果promise的执行结果是fulfilled或rejected,都会执行指定的回调函数。
2.需要执行上一次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) {// 返回一个promisereturn 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()

1.直接调用Promise.resolve方法.并产生一个成功的结果
2.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()

1.直接调用Promise.reject方法.并产生一个失败的结果

1. 使用示例

MyPromise.reject('失败了')
.catch(err => {console.log(err);
}) 

2. 实现过程

static reject(value) {
	// 返回一个新的promise
	return new MyPromise((_,reject)=>{
		reject(value);
	})
} 

九、all()

1.接收一个可迭代的集合对象(实现了iterable),并返回一个Promise实例
2.当前所有结果全部返回成功时,返回成功结果组成的数组
3.当任何一个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()

1.接收一个可迭代的集合对象(实现了iterable),全部执行完毕后返回一个Promise实例
2.返回多个对象组成的数组,通过status判断promise的执行状态
3.当任何一个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()

1.接收一个可迭代的集合对象(实现了iterable),并返回一个Promise
2.一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝 (哪个执行的速度快,返回哪个)
3.如果传递的可迭代集合是空的,那么返回的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这个promiseif (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.thenlet then = x.then;if (isFunction(then)) {// 因为存在同名函数 这里使用resolvePromiseThen代替resolvePromiseconst 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代替rejectPromiseconst rejectPromiseThen = r => {// 3.3. 如果resolvePromise和rejectPromise都被调用,或者同一个方法被调用了多次,以第一个调用为准,忽略其余调用if (isCalled) return;isCalled = true;reject(r);};// 3.7 如果then是一个函数,以x作为this来调用它,并且传入两个参数resolvePromise和rejectPromisethen.call(x, resolvePromiseThen, rejectPromiseThen);} else {// 3.8. 如果then不是一个函数,以x作为value来fulfill promiseresolve(x); // 此时x是普通值 直接返回结果}} catch (error) {// 3.6. 如果访问x.then属性导致抛出了一个异常(设为e),以e作为reason来reject promiseif (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方法返回的是一个Promiseconst 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被rejectreject(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被rejectreject(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被rejectreject(error);}});});}}});return promise2;}/** * catch方法 * 内部直接调用then方法 将回调函数传递到onRejected */catch(onRejected) {return this.then(undefined, onRejected);}/** * finaly方法 * 无论Promise的结果为成功或者失败 都会走到finally中,并将之前的结果原封不动的返回到下一次then中 */finally(onFinally) {// 返回一个promisereturn 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;// 返回一个新的promisereturn new MyPromise((resolve, reject) => {// 可能是thenableif (value && value.then && typeof value.then === 'function') {value.then(resolve, reject);} else resolve(value);});}/** * 静态reject方法 */static reject(value) {// 返回一个新的promisereturn 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; 
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值