В JavaScript использование "await" внутри цикла блокирует цикл?

выполните следующий цикл:

for(var i=0; i<100; ++i){
    let result = await some_slow_async_function();
    do_something_with_result();
}
  1. тут await блок цикла? Или i продолжайте увеличиваться, пока awaiting?

  2. порядок do_something_with_result() гарантированный последовательный в отношении i? Или это зависит от того, как быстро awaitфункция ed для каждого i?

3 ответов


  1. тут await блок цикла? Или i продолжайте увеличиваться, пока awaiting?

"блок" - не то слово, Но да,я не продолжает увеличиваться во время ожидания. Вместо этого выполнение возвращается туда, где async функция была вызвана, предоставляя обещание как возвращаемое значение, продолжая остальную часть кода, который следует после вызова функции, пока стек кода не был опорожнить. Затем, когда ожидание закончено, состояние функции восстанавливается, и выполнение продолжается внутри этой функции. Всякий раз, когда эта функция возвращается (завершается), соответствующее обещание, которое было возвращено ранее, разрешается.

  1. порядок do_something_with_result() гарантированный последовательный в отношении i? Или это зависит от того, как быстро awaitфункция ed для каждого i?

порядок гарантирую. Код после await также гарантируется выполнение только после того, как стек вызовов был пуст, то есть, по крайней мере, во время или после следующего microtask может выполнить.

посмотрите, как выводится в этом фрагменте. Обратите внимание, особенно, где говорится "после вызова теста":

async function test() {
    for (let i = 0; i < 2; i++) {
        console.log('Before await for ', i);
        let result = await Promise.resolve(i);
        console.log('After await. Value is ', result);
    }
}

test().then(_ => console.log('After test() resolved'));

console.log('After calling test');

Как говорит @realbart, он блокирует цикл, который затем сделает вызовы последовательными.

Если вы хотите запустить тонну ожидаемых операций, а затем обработать их все вместе, вы можете сделать что-то вроде этого:

const promisesToAwait = [];
for (let i = 0; i < 100; i++) {
  promisesToAwait.push(fetchDataForId(i));
}
const responses = await Promise.all(promisesToAwait);

вы можете протестировать async / await внутри цикла " FOR " следующим образом:

(async  () => {
        for (let i = 0; i < 100; i++) {
                await delay();
                console.log(i);
        }
})();

function delay() {
        return new Promise((resolve, reject) => {
                setTimeout(resolve, 100);
        });
}