myPromise.js
模拟实现方法
-
then方法: 用于注册成功和失败的回调函数
-
catch方法: 用于注册失败的回调函数
-
finally方法: 无论promise状态如何,都会执行的回调函数
-
all方法: 多个异步操作并行执行,等待所有操作完成后返回结果
-
allSettled方法: 多个异步操作并行执行,等待所有操作完成后返回结果,无论操作成功还是失败
-
race方法: 多个异步操作并行执行,返回第一个完成(成功或失败)的操作结果
-
any方法: 多个异步操作并行执行,返回第一个成功(只看成功)的操作结果
-
try方法: 用于处理同步或异步操作,返回promise对象
-
resolve方法: 用于返回成功的promise对象
-
reject方法: 用于返回失败的promise对象
// 处理循环任务
const resolvePromise = (p, resolve, reject,promiseNext) => {
// 处理循环任务
if (p === promiseNext) {
return reject(new TypeError('Uncaught (in promsie) TypeError:detected for promise #<Promsie>'));
}// 判断x是否是myPromise实例对象if (p instanceof MyPromise) {
p.then(resolve, reject);
} else {
resolve(p);
}
}// 手写一个promise
class MyPromise {
constructor(executor) {
// promise状态
this.status = 'pending';
// 成功的值
this.success = null;
// 失败的值
this.fail = null;
// 成功回调函数
this.successCallbacks = [];
// 失败回调函数
this.failCallbacks = [];// resolve函数 const resolve = (success) => { // 判断状态 if (this.status === 'pending') { this.status = 'fulfilled'; this.success = success; // 执行成功回调函数 if (this.successCallbacks.length) { this.successCallbacks.forEach(callback => callback(success)); } } } // reject函数 const reject = (fail) => { // 判断状态 if (this.status === 'pending') { this.status = 'rejected'; this.fail = fail; // 执行失败回调函数 if (this.failCallbacks.length) { this.failCallbacks.forEach(callback => callback(fail)); } } } try { // 执行executor函数 executor(resolve, reject); } catch (err) { reject(err) } } // then方法 then(onFulfilled, onRejected) { // 判断函数是否为空 onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : success => success; onRejected = typeof onRejected === 'function' ? onRejected : fail => { throw fail }; const primiseNext = new MyPromise((resolve,reject) => { // 判断成功状态 if (Object.is(this.status, 'fulfilled')) { // 使用微任务 queueMicrotask(() => { try { const result = onFulfilled(this.success); resolvePromise(result, resolve, reject,primiseNext); } catch (error) { reject(error); } }) } // 判断失败状态 if (Object.is(this.status, 'rejected')) { queueMicrotask(() => { try { const result = onRejected(this.fail); resolvePromise(result, resolve, reject,primiseNext); } catch (error) { reject(error); } }) } // 初始的状态 if (Object.is(this.status, 'pending')) { // 收集成功回调 this.successCallbacks.push(() => { queueMicrotask(() => { try { const result = onFulfilled(this.success); resolvePromise(result, resolve, reject,primiseNext); } catch (error) { reject(error); } }) }) // 收集失败回调 this.failCallbacks.push(( () => { queueMicrotask(() => { try { const result = onRejected(this.fail); resolvePromise(result, resolve, reject,primiseNext); } catch (error) { reject(error); } }) })) } } ); // 返回新的promise实例对象 return primiseNext; } // catch方法 catch(onRejected) { return this.then(undefined, onRejected); } // 静态方法 finally(fn) { return this.then(success => { fn(); return success; }, fail => { fn(); throw fail }); } // resolve 静态方法 static resolve(value) { // 是否是myPromise实例对象 if (value instanceof MyPromise) { return value; } // 不是的话需要包装成myPromise实例对象 return new MyPromise(resolve => resolve(value)); } // reject静态方法 static reject(fail) { // 是否是myPromise实例对象 if (fail instanceof MyPromise) { return fail; } // 包装成myPromise实例对象 return new MyPromise((resolve, reject) => reject(fail)); } // 实现一个all静态方法, 要不全部执行成功,要不失败退出循环 static all(promiseArr) { // 返回一个promise结果 return new MyPromise((resolve, reject) => { const len = promiseArr.length; // 判断参数长度是否为空 if (Object.is(len, 0)) { resolve([]); } else { // 要不全部执行成功,要不失败退出循环 const res = []; let successCount = 0; for (let i = 0; i < len; i++) { promiseArr[i]?.then(data => { res[i] = data; // 判断是否完成全部,全部执行成功之间触发resolve返回结果 if (Object.is(++successCount, len)) { resolve(res); } }, err => { reject(err); return; // 结果循环 }) } } }) } // allSettled静态方法 将所有成功或者失败都返回结果 static allSettled(promiseArr) { return new MyPromise((resolve, reject) => { if (Object.is(promiseArr.length, 0)) { resolve([]); } else { const res = []; promiseArr.forEach((promise,index) => { promise.then(sucess => { res[index] = ({status: 'fulfilled', value: sucess}); },fail => { res[index] = ({status: 'rejected', reason: fail}); }) }); resolve(res); } }) } // race静态方法, 有一个执行成功或失败,就返回结果 static race(promiseArr) { // 返回一个promise结果 return new MyPromise((resolve, reject) => { const len = promiseArr.length; // 判断参数长度是否为空 if (Object.is(len, 0)) { resolve([]); } else { // 有一个执行成功或失败,就返回结果 for (const promise of promiseArr) { promise.then(resolve, reject); } } }) } // any静态方法, 有一个执行成功,就返回结果 static any(promiseArr) { // 返回一个promise结果 return new MyPromise((resolve, reject) => { const len = promiseArr.length; // 判断参数长度是否为空 if (Object.is(len, 0)) { reject(new AggregateError('All promises were rejected')); } else { // 有一个执行成功,就返回结果 let failCount = 0; for (let i = 0; i < len; i++) { promiseArr[i]?.then(sucess => { resolve(sucess); return; // 结束循环 }, fail => { // 判断是否完成全部,全部执行失败之间触发reject返回结果 if (Object.is(++failCount, len)) { reject(fail); } }); } } }) } // try静态方法 static try (fn) { return new MyPromise((resolve, reject) => { try { resolve(fn()); } catch (error) { reject(error); } }) }}
以下做一些简答测试
测试MyPromise
const pro = new MyPromise((resolve, reject) => {
resolve('success');
}).then(res => {
console.log('then1', res); // then1 success
x
}).then(res => {
console.log('then2', res); // then2 undefined
}).catch(err => {
console.log('catch1', err); // 多个catch只执行一个
}).catch(err => {
console.log('catch2', err);
}).finally(() => {
console.log('finally1');
}).finally(() => {
console.log('finally2');
})
测试MyPromise.all方法
MyPromise.all([
new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(100);
}, 1000);
}),
new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(200);
}, 2000);
}),
new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(300);
}, 3000);
})
]).then(res => {
console.log(res); // [ 100, 200, 300 ]
})
测试allSettled方法,将成功和失败都返回
MyPromise.allSettled([
new MyPromise((resolve, reject) => {
resolve(100);
}),
new MyPromise((resolve, reject) => {
reject(200);
}),
new MyPromise((resolve, reject) => {
resolve(300);
})
]).then(res => {
console.log(res); // [ { status: 'fulfilled', value: 100 }, { status: 'rejected', reason: 200 }, { status: 'fulfilled', value: 300 } ]
})
测试MyPromise.any方法 有一个成功就可以成功结果
MyPromise.any([
new MyPromise((resolve, reject) => {
setTimeout(() => {
reject(100);
}, 10);
}),
new MyPromise((resolve, reject) => {
setTimeout(() => {
reject(200);
}, 20);
}),
new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(300);
}, 30);
})
]).then(res => {
console.log(res); // 300
})
测试MyPromise.race方法,有一个成功或者失败就可以返回结果
MyPromise.race([
MyPromise.resolve(1),
MyPromise.reject(2),
MyPromise.resolve(3)
]).then(res => {
console.log('promise resolve', res); // 1
}).catch(err => {
console.log('promise reject', err); // 1
})
测试MyPromise.try方法, 可以捕获同步代码异常
MyPromise.try(() => {
// 在这里面其实就是加了try catch这样功能,并优雅返回promise
console.log('try success');
}).then(res => {
console.log(res); // try success
}).catch(err => {
console.log(err);
})