reactjs - 并行执行 Promise 的最佳/最快方式?(反应)
问题描述
假设我需要获取数据来创建卡片。使用 Promise 获取这些数据的最快方法是什么?这是我目前的做法:
async function getCards() {
const promises = []
for (let i = 0; i < 10; i++) {
promises.push(getCard(i))
}
const cards = await Promise.allSettled(promises)
setCards(cards)
}
async function getCard(i) {
const property1 = await getProperty1(i)
const property2 = await getProperty2(i)
const property3 = await getProperty3(i)
const card = <div>
<div>Property 1: {property1}</div>
<div>Property 2: {property2}</div>
<div>Property 3: {property3}</div>
</div>
return card
}
出于我的目的,我不需要 Promise.allSettled,因为我不需要等待所有 10 张卡都完成等待(我可能只是创建一个组件),我可以在它们完成时渲染每张卡。但我仍然希望它尽可能快地并行/执行。我还有什么其他选择?有没有更好的方法来处理我在 getCard 中所做的事情?
解决方案
如果getPropertyN()
确实是异步操作(例如网络请求),则将并行getCards()
运行循环中的所有调用for
,以便它们同时处于运行状态,通常会减少端到端时间与连续运行它们。
还有一些其他因素在起作用,例如接收主机一次收到一堆请求时会做什么。如果它一次只处理一个,那么您可能不会获得很多。但是,如果主机有任何并行性,那么您肯定会看到通过同时运行多个请求来加速。
请注意,您的getCard(i)
实现正在序列化对 的三个调用getProperty1()
,这可能也可以与以下内容并行完成getProperty2()
:getProperty3()
const [property1, property2, property3] = await Promise.all([
getProperty1(i),
getProperty2(i),
getProperty3(i)
]);
而不是这个:
const property1 = await getProperty1(i)
const property2 = await getProperty2(i)
const property3 = await getProperty3(i)
要记住的另一件事是浏览器(例如fetch()
调用)只会向同一主机发出 N 个同时请求(其中 N 约为 6)。一旦超过了对同一主机同时进行的所有请求的数量,那么浏览器会将其余请求排队,直到前一个请求完成。它的实现方式不会减慢处理超过最大请求的速度,但是在浏览器的限制之后您不会获得更多的并行性。如果您从不同的 Javascript 环境(例如 nodejs)运行此代码,则该限制将不适用,因为这是特定于浏览器的事情。
请注意,实现并行性的关键是同时启动多个正在运行的请求。没有要求您Promise.allSettled()
在对任何结果进行操作之前使用,除非您需要在处理结果之前按顺序获取所有结果。
如果结果可以在完成时单独处理并且可以按任何顺序处理,您也可以这样编写代码,而无需使用以下代码Promise.allSettled()
:
getProperty(1).then(processResult).catch(processErr);
getProperty(2).then(processResult).catch(processErr);
getProperty(3).then(processResult).catch(processErr);
注意:我也没有在您的代码中看到任何错误处理。任何外部网络请求都可能失败,您必须有一些处理程序来处理被拒绝的承诺。
推荐阅读
- cuda - cuda 从设备内存中复制内核中动态 malloc 的数据
- sapui5 - sap.m.TablePersoController 多表个性化
- system-verilog - SystemVerilog 中单位常量文字的符号扩展
- python - 按其他数据框列过滤熊猫行
- xml - 如何使用 powershell 转换 XML 中的属性?
- php - 如何多次更新行laravel
- c# - SqlServer2012-错误 40-无法在 SQL Server 中打开连接
- vim - Vim 符号:使用 RltvNmbr 脚本的 Linter 指示
- c# - c# odata (v4) - power bi 报告:发现意外的“StartArray”节点
- c++ - 如何设置动态创建的 CMFCToolbar 的原始状态?