简体   繁体   中英

Why ESLint no-await-in-loop not working with for await of?

for await of — supposed to be used with asynchronous iterators, it awaits each promise within iterator and handles response of each awaited promise in its body. From MDN docs this syntax can be used also with sync iterators, so

I have the following code examples that work similar:

(async () => {
    const entityIds = [1, 2, 3, 4];
    
    for await (const id of entityIds) {
        console.log(await getEntityById(id));
    }
})();

And:

(async () => {
    const entityIds = [1, 2, 3, 4];
    
    for (const id of entityIds) {
        console.log(await getEntityById(id)); // ESLint: Unexpected `await` inside a loop.(no-await-in-loop)
    }
})();

But in the 2nd example I'm getting eslint warning about the rule no-await-in-loop . The question is: why? Each iteration of these 2 loops will await for async function completes, but the eslint is not gonna react on 1st case at all.

The no-await-in-loop rule in ESLint is supposed to protect you from accidentally processing some data sequentially. The reasoning is that often having an await in a loop is not intentional because it is more efficient to process the data in parallel. Thus all usages of await in a loop are considered a "mistake" when the rule is turned on.

Using for await...of is explicitly considered "intentional" by the rule. Checking the rule's tests (bottom of the documentation page) the following part is listed as valid code:

valid: [
    // ...

    // Asynchronous iteration intentionally
    "async function foo() { for await (var x of xs) { await f(x) } }"
],

while any usage of await in any other loop construct is invalid. Including using await inside a loop inside a for await...of :

invalid: [
    // ...

    // In a nested loop of for-await-of
    { code: "async function foo() { for await (var x of xs) { while (1) await f(x) } }", errors: [error] }
]

The reasoning most likely is that using for await...of you opt into sequential processing. If you process an asynchronous iterable, chances are very high that you cannot do that in parallel and it would be an error if you try. If you are processing a synchronous iterable which produces promises there is still a chance that you cannot correctly do this in parallel.

ESLint cannot actually detect if you instead have a synchronous iterable which produces synchronous results like an array iterator, therefore, it assumes it is one of the first two options.


In my opinion, the rule is flawed as it is all or nothing. Enabling it means you want no loops with await in them. There are still valid cases where you want sequential processing with for...of and an await inside. Which means that your code is likely to be littered with temporary disables of the rule whenever you do not need it.

My suggestion is to disable the no-await-in-loop rule and exercise common sense for when you use sequential and when you use parallel processing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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