<-Home
实现Promise: all、race、allSettled、any
准备工作
function isNative(Ctor){
return typeof Ctor === 'function' && /native code/.test(Ctor.toString());
}
function macroTask(cb) {
const channel = new MessageChannel();
channel.port1.onmessage = cb;
channel.port2.postMessage(1);
}
class AggregateError extends Error {
constructor(message: string) {
super(message);
this.message = message;
}
}
实现 Promise.all
- 参数有且仅有一个可迭代对象,意思是指 装载了 Symbol.iterator 方法;
- 当不满足第1个条件时,抛出一个TypeError 错误;
- 参数里面的所有项要么是一个Promise 实例,或者是一个LikePromis
- 临时申请一个结果数组,对可迭代对象中的所有项进行处理,结果放入临时数组, 完成后执行 6 (pending)
- 迭代过程中如果有项触发 reject 则退出 for 体;(fulfilled:rejected)
- resolve 临时数组(fulfilled:resolved)
function promiseAll(values) {
return new Promise((resolve, reject) => {
if (!isNative(values[Symbol.iterator]))
return reject(new TypeError(`${typeof values} is not iterable (cannot read property Symbol(Symbol.iterator))`));
const results = [];
let haveAnyReject = false;
for (let item of values) {
// 如果在结束循环之前的其中任何一个触发了reject 则break;
if (haveAnyReject) break;
try {
item.then(res => results.push(res)).catch(reason => {
haveAnyReject = true;
reject(reason);
});
} catch (err) {
Promise.resolve().then(() => { results.push(item) });
}
}
// setTimeout(resolve, 0, results);
// queueMicrotask(() => resolve(results));
!haveAnyReject && macroTask(() => resolve(results));
});
}
实现 Promise.race
- 参数有且仅有一个可迭代对象,意思是指 装载了 Symbol.iterator 方法;
- 当不满足第1个条件时,抛出一个TypeError 错误;
- 参数里面的所有项要么是一个Promise 实例,或者是一个LikePromis
- 可迭代对象里面的任意一个触发resolve|reject 则 race 方法resolve|reject(fulfilled)
- 如果第4 个条件不满足, 则返回的promise实例是pending状态 (pending)
function promiseRace(values) {
return new Promise((resolve, reject) => {
if (!isNative(values[Symbol.iterator]))
return reject(new TypeError(`${typeof values} is not iterable (cannot read property Symbol(Symbol.iterator))`));
for(let item of values) {
try {
item.then(res => resolve(res)).catch(reason => reject(reason));
} catch (err) {
Promise.resolve().then(() => resolve(item));
}
}
});
}
实现Promise.allSellted
- 参数有且仅有一个可迭代对象,意思是指 装载了 Symbol.iterator 方法;
- 当不满足第1个条件时,抛出一个TypeError 错误;
- 参数里面的所有项要么是一个Promise 实例,或者是一个LikePromis
- 临时申请一个结果数组,对可迭代对象中的所有项进行处理,结果放入临时数组, 完成后执行 6 (pending)
- resolve 临时数组(fulfilled:resolved)
function promiseAllSellted(values) {
return new Promise((resolve, reject) => {
if (!isNative(values[Symbol.iterator]))
return reject(new TypeError(`${typeof values} is not iterable (cannot read property Symbol(Symbol.iterator))`));
const results = [];
for (let item of values) {
try {
item.then(res => results.push(res)).catch(reason => results.push(reason));
} catch (err) {
Promise.resolve().then(() => { results.push(item) });
}
}
macroTask(() => resolve(results));
});
}
实现Promise.any
- 参数有且仅有一个可迭代对象,意思是指 装载了 Symbol.iterator 方法;
- 当不满足第1个条件时,抛出一个TypeError 错误;
- 参数里面的所有项要么是一个Promise 实例,或者是一个LikePromis
- 可迭代参数中任意一项触发 resolve 则整个any 方法返回的promise 有 pending ——> fulfilled(resolved)
- 如果第4项不满足则抛出一个AggregateError (Aggregate 合计,全部,所有)
function promiseAny(values) {
return new Promise((resolve, reject)=> {
if (!isNative(values[Symbol.iterator]))
return reject(new TypeError(`${typeof values} is not iterable (cannot read property Symbol(Symbol.iterator))`));
let haveAnyResolved = false;
for (let item of values) {
if (haveAnyResolved) break;
try {
item.then(res => {
resolve(res);
// 此处不能直接break, 因为跨级了,这里属于 then cb 的作用域块了
haveAnyResolved = true;
}).catch(reason => reason);
} catch(e) {
resolve(item);
break;
}
}
macroTask(() => {
reject(new AggregateError('All promise is rejected'));
});
});
}