Promise 并发(JS)
在 async 函数中,“过度 await”代码非常普遍。将 Promise.all() 与异步函数一起使用,可以有效的实现并发。
例如,两个异步函数 fetchA, fetchB:
1 2 3 4 5 6 7 8 9
| async function fetchA() { const response = await fetch("/path/a"); return await response.json(); }
async function fetchB() { const response = await fetch("/path/b"); return await response.json(); }
|
await 运算符会让异步函数串行执行,执行 fetchA()获得结果之后,才去执行 fetchB()。如下:
1 2 3 4 5
| async function awaitFunc() { const a = await fetchA(); const b = await fetchB(); return handleResult(a, b); }
|
我们可以使用 Promise.all 让异步函数并发执行。
1 2 3 4
| async function promiseAllFunc() { const [a, b] = await Promise.all([fetchA(), fetchB()]); return handleResult(a, b); }
|
Promise 类提供了以下四种异步任务的并发。
Ox01 Promise.all()
Promise.all() 静态方法接受一个 Promise 可迭代对象作为输入,并返回一个 Promise。当所有输入的 Promise 都被兑现时,返回的 Promise 也将被兑现(即使传入的是一个空的可迭代对象),并返回一个包含所有兑现值的数组。
- 所有的 Promise 都被兑现时兑现,并返回一个包含所有兑现值的数组;
- 在任何一个输入的 Promise 被拒绝时立即拒绝,并带回被拒绝的原因;
1 2 3 4 5 6 7 8 9 10
| const promise1 = Promise.resolve(3); const promise2 = 42; const promise3 = new Promise((resolve, reject) => { setTimeout(resolve, 100, "foo"); });
Promise.all([promise1, promise2, promise3]).then((values) => { console.log(values); });
|
Ox02 Promise.allSettled()
Promise.allSettled() 静态方法将一个 Promise 可迭代对象作为输入,并返回一个单独的 Promise。当所有输入的 Promise 都已敲定时(包括传入空的可迭代对象时),返回的 Promise 将被兑现,并带有描述每个 Promise 结果的对象数组。
- 在所有的 Promise 都被敲定时兑现,返回一个带有描述每个 Promise 结果的对象数组;
- 永远不会被 reject;
1 2 3 4 5 6 7 8 9 10 11 12 13
| Promise.allSettled([ Promise.resolve(33), new Promise((resolve) => setTimeout(() => resolve(66), 0)), 99, Promise.reject(new Error("一个错误")), ]).then((values) => console.log(values));
|
- status: 一个字符串,要么是 “fulfilled”,要么是 “rejected”,表示 promise 的最终状态。
- value: 仅当 status 为 “fulfilled”,才存在。promise 兑现的值。
- reason: 仅当 status 为 “rejected”,才存在,promsie 拒绝的原因。
Ox03 Promise.any()
在任意一个 Promise 被兑现时兑现;仅在所有的 Promise 都被拒绝时才会拒绝。
1 2 3 4 5 6 7 8 9
| const promise1 = Promise.reject(0); const promise2 = new Promise((resolve) => setTimeout(resolve, 100, "quick")); const promise3 = new Promise((resolve) => setTimeout(resolve, 500, "slow"));
const promises = [promise1, promise2, promise3];
Promise.any(promises).then((value) => console.log(value));
|
Ox04 Promise.race()
在任意一个 Promise 被敲定时敲定。换句话说,在任意一个 Promise 被兑现时兑现;在任意一个的 Promise 被拒绝时拒绝。
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 33 34 35 36 37 38 39 40 41 42 43 44 45
| function sleep(time, value, state) { return new Promise((resolve, reject) => { setTimeout(() => { if (state === "兑现") { return resolve(value); } else { return reject(new Error(value)); } }, time); }); }
const p1 = sleep(500, "一", "兑现"); const p2 = sleep(100, "二", "兑现");
Promise.race([p1, p2]).then((value) => { console.log(value); });
const p3 = sleep(100, "三", "兑现"); const p4 = sleep(500, "四", "拒绝");
Promise.race([p3, p4]).then( (value) => { console.log(value); }, (error) => { } );
const p5 = sleep(500, "五", "兑现"); const p6 = sleep(100, "六", "拒绝");
Promise.race([p5, p6]).then( (value) => { }, (error) => { console.error(error.message); } );
|
参考
MDN Web 开发技术:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise