【问题标题】:How to implement multithreading in loop of api calls nodejs如何在api调用nodejs的循环中实现多线程
【发布时间】:2021-10-05 07:58:50
【问题描述】:

我在一个数组中有数千个文本对象。 我想将每个文本发送到 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 会在这里工作吗?

谢谢:)

【问题讨论】:

    标签: javascript node.js multithreading performance worker


    【解决方案1】:

    当您需要 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));
    }
    

    【讨论】:

    • 谢谢你的回答,在这里我有一个疑问,如果任何承诺失败了,那么对于这个承诺,我不想将textId 推入textIds 数组,并且对于单个 api 调用,我的结果是太大的文档,它不会损害性能吗?而且我不是用await来得到所有promise的结果吗?
    • 听起来你想忽略个别承诺的例外情况。因此,您的承诺将是 axios.post("API", {text:elem.text}).then(res =&gt; res.id).catch(ex =&gt; null) 然后您可以过滤结果数组以删除空值。
    猜你喜欢
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-16
    • 1970-01-01
    • 2014-11-29
    • 1970-01-01
    相关资源
    最近更新 更多