简体   繁体   English

优雅的解决方案 - 嵌套 for 循环(eslint no-await-in-loop)

[英]Elegant solution - Nested for loops (eslint no-await-in-loop)

I have some code that works broadly as follows:我有一些广泛工作的代码如下:

function getRegionUsers(region) {
    return new Promise((resolve) => {
        setTimeout(() => {
            if (region === "emea") {
                return resolve(["dave", "mike", "steve"]);
            }
            return resolve(["kiki", "maya", "yukiko"]);
        }, 1000);
    });
}

function sendMail(user, region) {
    console.info(`sendMail called: ${user} (${region})`);
}

async function test() {
    const regions = ["emea", "apac"];
    for (const region of regions) {
        const users = await getRegionUsers(region); // This line is my issue
        for (const user of users) {
            sendMail(user, region);
        }
    }
}
test();

You can ignore the first 2 functions, those just help illustrate the issue.您可以忽略前两个功能,它们只是帮助说明问题。 The issue is the 3rd function which causes a linter error ( eslint: no-await-in-loop ) which makes sense as the await will hold up the execution of each iteration of my for loop.问题是第三个 function 会导致 linter 错误 ( eslint: no-await-in-loop ),这是有道理的,因为 await 将阻止我for循环的每次迭代的执行。

The solution I keep seeing is to use Promise.all which is fine except I need to keep track of both user and region so I can pass it to the sendMail function. I therefore end up with something like this:我一直看到的解决方案是使用Promise.all这很好,除了我需要跟踪用户和区域以便我可以将它传递给sendMail因此我最终得到这样的结果:

async function test() {
    const regions = ["emea", "apac"];

    const userPromises = regions.map((r) => getRegionUsers(r));
    const regionUsers = await Promise.all(userPromises);

    for (const [i, region] of regions.entries()) {
        for (const user of regionUsers[i]) {
            sendMail(user, region);
        }
    }
}
test();

This seems messy and inelegant since I essentially duplicate the regions for loop and it's harder to follow.这看起来凌乱且不雅,因为我基本上复制for循环区域并且更难理解。 It also gets messier once you deal with error catching or if you have another level or two of nested for loops.一旦您处理错误捕获或者如果您有另一层或两层嵌套 for 循环,它也会变得更加混乱。

Does anyone have a more elegant solution (other than just telling ESLint to ignore the line) even if it's just a neater way to write it?有没有人有更优雅的解决方案(除了告诉 ESLint 忽略该行),即使它只是一种更简洁的编写方式?

I would map the regions with an async function. The async function always returns a promise (no need to add an explicit return statement).我会 map 具有异步 function 的区域。异步 function 始终返回 promise(无需添加显式return语句)。 And the promises can be awaited with Promise.all .并且可以使用Promise.all等待承诺。

async function test() {
    const regions = ["emea", "apac"];

    const promises = regions.map(async region => {
        const users = await getRegionUsers(region);
        for (const user of users) {
            sendMail(user, region);
        }
    });
    await Promise.all(promises);
}

This should fix the problem reported by no-await-in-loop .这应该可以解决no-await-in-loop报告的问题。 It is possible though that other ESLint rules, depending on your configuration, will start to complain.根据您的配置,其他 ESLint 规则可能会开始报错。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM