Promise 的并发方法: all,allSettled,any,race。这些方法都会接受 promises 数组,返回一个新的 Promise。
Promise.all
成功:所有传入的 promise 状态都为 fulfilled,传回所有的成功的结果数组
失败:只要有一个 promise 状态为 rejected,直接传回失败结果
核心特征(独立、缺一不可):
-
业务逻辑依赖所有任务的成功结果(缺一不可)
-
快速失败(任一任务失败则整体终止,无需等待其他任务)
适用场景:
-
资源预先加载
-
依赖多接口数据加载
function PromiseAll(promises) {
return new Promise((resolve, reject) => {
if(!Array.isArray(promises)) {
reject(new TypeError('输入参数错误'));
}
let n = promises.length;
let results = new Array(n);
let fullfilledCnt = 0;
if(n == 0) {
return resolve(results);
}
promises.forEach((promise, i)=> {
Promise.resolve(promise).then(result => {
results[i] = result;
fullfilledCnt ++;
if(fullfilledCnt == n) {
resolve(results);
}
}).catch(err => {
reject(err);
});
});
});
};
// const p1 = Promise.resolve(1);
// const p2 = new Promise(resolve => setTimeout(() => resolve(2), 1000));
// PromiseAll([p1, p2]).then(console.log); // [1, 2](约1m后)
// const p3 = Promise.reject('出错了');
// PromiseAll([p1, p3]).catch(console.error); // '出错了'(立即)
Promise.allSettled
成功:所有传入的 promise 状态都为 fulfilled 或 rejected,传回结果为数组,包含状态以及成功或失败的结果
核心特征:完整结果反馈; 不因单个失败而中断
适用场景:
-
日志上传
-
非核心资源预加载
function PromiseAllSettled(promises) {
return new Promise((resolve, reject) => {
if(!Array.isArray(promises)) {
reject(new TypeError('输入参数错误'));
}
let n = promises.length;
let results = new Array(n);
let cnt = 0;
if(n == 0) {
return resolve(results);
}
promises.forEach((promise, i)=> {
Promise.resolve(promise).then(value => {
results[i] = { stats: 'fullfilled', value };
}).catch(error => {
results[i] = { stats: 'rejected', error };
}).finally(() => {
cnt ++;
if(cnt == n) {
resolve(results);
}
});
});
});
};
// const promise1 = Promise.resolve(3);
// const promise2 = Promise.reject(new Error('Promise 2 failed'));
// const promise3 = new Promise((resolve) => {
// setTimeout(resolve, 100, 'foo');
// });
// PromiseAll([promise1, promise2, promise3])
// .then(values => {
// console.log(values); // 不会执行
// })
// .catch(error => {
// console.error(error); // 输出: Error: Promise 2 failed
// });
Promise.any
成功:第一个完成的 promise 的状态为 fulfilled,返回成功结果
失败:所有 promise 状态为 rejected,返回失败的数组
特征:结果单一性;全败才败(兜底)
场景:多源数据兜底获取、多节点服务器可用性检测
function PromiseAny(promises) {
return new Promise((resolve, reject) => {
if(!Array.isArray(promises)) {
reject(new TypeError('输入参数错误'));
}
let n = promises.length;
if(n == 0) return;
let rejectCnt = 0;
let errors = new Array(n);
promises.forEach((promise, i)=> {
Promise.resolve(promise).then(value => {
resolve(value);
}).catch(error => {
rejectCnt ++;
errors[i] = error
if(rejectCnt == n) {
reject(new AggregateError(error, "所有promises都被rejected"));
}
});
});
});
};
// const resolveAfter = (value, delay) =>
// new Promise(resolve => setTimeout(() => resolve(value), delay));
// const rejectAfter = (reason, delay) =>
// new Promise((_, reject) => setTimeout(() => reject(reason), delay));
// // 有一个成功(第一个成功的结果被返回)
// const test1 = async () => {
// const p1 = rejectAfter('p1失败', 100);
// const p2 = resolveAfter('p2成功', 200);
// const p3 = resolveAfter('p3成功', 150);
// try {
// const result = await PromiseAny([p1, p2, p3]);
// console.log('测试1结果:', result);
// } catch (err) {
// console.error('测试1错误:', err);
// }
// };
// test1();
Promise.race
成功:第一个完成的 promise 的状态为 fulfilled,返回成功结果
失败:第一个完成的 promise 的状态为 rejected,返回失败结果
特征:竞速性,最快的响应结果,结果具有单一性
场景:cdn 命中(要的就是最快的响应);用户请求同一接口(避免重复刷新);接口请求超时
function PromiseRace(promises) {
return new Promise((resolve, reject) => {
if(!Array.isArray(promises)) {
reject(new TypeError('输入参数错误'));
}
let n = promises.length;
if(n == 0) return;
promises.forEach((promise, i)=> {
Promise.resolve(promise).then(value => {
resolve(value);
}).catch(error => {
reject(error);
});
});
});
};
// // 测试正常场景
// const p1 = new Promise(resolve => setTimeout(() => resolve(1), 100));
// const p2 = Promise.resolve(2);
// PromiseRace([p1, p2]).then(console.log); // 2(立即,p2先成功)
// // 测试失败场景
// const p3 = Promise.reject('出错了');
// const p4 = new Promise(resolve => setTimeout(resolve, 200));
// PromiseRace([p4, p3]).catch(console.error); // '出错了'(立即,p3先失败)
手写 Promise 并发方法解析
997

被折叠的 条评论
为什么被折叠?



