【问题标题】:Running for loop in "parallel" using async/await promises使用 async/await 承诺在“并行”中运行 for 循环
【发布时间】:2021-03-30 09:26:49
【问题描述】:

我目前有一个这样的 for 循环:

async myFunc() {
    for (l of myList) {
        let res1 = await func1(l)
        if (res1 == undefined) continue

        let res2 = await func2(res1)
        if (res2 == undefined) continue

        if (res2 > 5) {
            ... and so on
        }
    }
}

问题是 func1、func2 是返回承诺的网络调用,我不希望它们在等待它们时阻塞我的 for 循环。所以我不介意与 myList[0] 和 myList[1] 并行工作,也不关心列表项的处理顺序。

我怎样才能做到这一点?

【问题讨论】:

  • 您可以让他们解决/拒绝该承诺,然后在循环中调用它们,而不是让他们返回一个承诺。如果您不想处理回复。
  • 如果有更多代码,看看是否一切都设置正确,那就太好了。通常你会在等待 Promise 之后使用.then() 做一些事情,以确保它按顺序运行。然后你可以在第二次调用中调用另一个函数,就像.then((result) => { callAnotherFunction(result); })
  • @Frizzant - 在async 函数中,您使用await(就像上面的OP 所做的那样),而不是.then(95% 的时间)。

标签: javascript typescript async-await promise


【解决方案1】:

我会通过编写一个函数来处理您正在按顺序处理的一个值:

async function doOne(l) {
    let res1 = await func1(l);
    if (res1 == undefined) {
        return /*appropriate value*/;
    }

    let res2 = await func2(res1);
    if (res2 == undefined) {
        return /*appropriate value*/;
    }

    if (res2 > 5) {
        // ... and so on
    }
}

然后我会使用 Promise.allmap 来启动所有这些并让它们并行运行,将结果作为数组获取(如果您需要结果):

function myFunc() {
    return Promise.all(myList.map(doOne)); // Assumes `doOne` is written expecting to be called via `map` (e.g., won't try to use the other arguments `map` gives it)
    // return Promise.all(myList.map(l => doOne(l))); // If we shouldn't make that assumption
}

如果myList 是(或可能是)非数组可迭代,则使用Array.from 获取一个数组以使用map

function myFunc() {
    return Promise.all(Array.from(myList.map(doOne)));
}

(或者使用 for-of 循环推送到数组。)

如果您不希望处理列表中的一个条目失败以防止看到处理列表中其他条目的结果,请使用Promise.allSettled 而不是Promise.all。 (请注意,它们都将以任何方式启动,唯一的区别是当至少其中一个失败时您是否看到成功的结果。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-12
    • 1970-01-01
    • 1970-01-01
    • 2021-10-30
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多