javascript - 如何在api调用nodejs的循环中实现多线程
问题描述
我在一个数组中有数千个文本对象。我想将每个文本发送到 API 并将结果保存到一个集合中,并在成功结果时更新另一个集合。
这是我的实现,
let arr = [
{
textId: "123",
text: "This is stackoverflow"
},
{
textId: "678",
text: "I love stackoverflow"
}
];
let textIds = [];
for(let i=0;i<arr.length;i++){
const result = await axios.post("API", {text:arr[i].text});
if(result && result.status === 200){
await db.collections("solutions").insertOne({...arr[i], result});
textIds.push(arr[i].textId);
}
}
await db.collections("texts").updateMany({textId:{"$in":textIds}},{"$set":{solutionFlag: true}});
当我像 10k、20k 文本一样迭代时,这会导致性能不佳。10k 条文本大约需要 1 小时。如何优化此代码。会worker_threads
在这里工作吗?
谢谢:)
解决方案
当您需要 CPU 密集型作业并发时使用工作线程。这是 IO 密集型并发。因此,您只需使用普通的 Promise 即可完成此操作。您应该收集此调用返回的承诺,并像这样同时运行它们:
const promises = arr.map(elem => axios.post("API", {text:elem.text}));
const results = Promises.all(promises);
发出这么多并发请求可能不是您想要的。在这种情况下,请执行以下操作:
var textIds = [];
for (var i = 0; i < n/concurrency_factor; ++i) {
const promises = arr.slice(i*concurrency_factor, (i+1)*concurrency_factor);
const results = Promises.all(promises);
textIds = textIds.concat(results.map(res => res.id));
}
推荐阅读
- javascript - codeandbox.io 无法指向除“index.html”之外的任何内容
- javascript - JQuery 每个方法都没有正确设置“this”参数
- spring - Spring & JUnit 5 - 当@AfterAll 必须为静态时如何清除数据库
- angular - 升级到 NativeScript 6 后无法解析 db.worker.js 文件的路径
- java - 有没有办法在 JVM 选项中解决可运行 jar 包中模块的模块路径?
- javascript - 我需要从 then() 返回一个值
- javascript - javascript 电子函数 shell.openExternal(url) 需要时间来打开链接
- c++ - 通过设置(1000 万)点 3D 创建 3D 表面(CGAL::make_surface_mesh)
- azure-devops - 从 Azure DevOps Release Pipeline 获取发布和内部版本号以显示在网站上
- visual-studio-code - wsl的代码路径是什么,因此在用户配置文件中安装了Vscode