• 根据PromiseA+规范从零实现Promise【这一次,带你彻底搞懂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
    • 2
    • 3
    • 4
    • 5

    二、要求

    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;
    		}
    	}
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    小结

    • 定义常量保存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;}
    } 
    
    • 1
    • 2
    • 3
    • 4

    小结

    • 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);
    }); 
    
    • 1
    • 2
    • 3
    • 4

    2. 实现过程

     /** * catch方法 * 内部直接调用then方法 将回调函数传递到onRejected */catch(onRejected) {return this.then(undefined, onRejected);} 
    
    • 1

    六、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)
    }) 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    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);}});});}});
    } 
    
    • 1
    • 2

    七、静态resolve()

    1.直接调用Promise.resolve方法.并产生一个成功的结果
    2.value可能存在的情况* 普通值和空值 - 使用resolve返回当前值* 是一个Promise实例 - 直接返回此结果* thenable对象

    1. 使用示例

    MyPromise.resolve(MyPromise.resolve(MyPromise.resolve('成功了')))
    .then(res => {console.log(res);
    }) 
    
    • 1
    • 2
    • 3

    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);
    	})
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    八、静态reject()

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

    1. 使用示例

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

    2. 实现过程

    static reject(value) {
    	// 返回一个新的promise
    	return new MyPromise((_,reject)=>{
    		reject(value);
    	})
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    九、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)
    }) 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    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;}}});
    } 
    
    • 1
    • 2

    十、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)
    }) 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    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;}}});
    } 
    
    • 1
    • 2

    十一、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);}); 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    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);}}});
    } 
    
    • 1
    • 2

    十二、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; 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
  • 相关阅读:
    2023 年最佳 Android 数据恢复软件工具
    鸿鹄工程项目管理系统em Spring Cloud+Spring Boot+前后端分离构建工程项目管理系统
    【SQLite】环境安装
    贪心算法——背包问题
    深入理解二叉树:结构、遍历和实现
    R语言作业wine 数据
    关于电路的输入阻抗与输出阻抗的理解
    【Java】static关键字,内部类
    性能测试有哪些我们测试员必须要掌握的知识点?
    前端面试题JavaScript篇——2022-09-22
  • 原文地址:https://blog.csdn.net/pfourfire/article/details/126583945