В JavaScript использование "await" внутри цикла блокирует цикл?
выполните следующий цикл:
for(var i=0; i<100; ++i){
let result = await some_slow_async_function();
do_something_with_result();
}
тут
await
блок цикла? Илиi
продолжайте увеличиваться, покаawait
ing?порядок
do_something_with_result()
гарантированный последовательный в отношенииi
? Или это зависит от того, как быстроawait
функция ed для каждогоi
?
3 ответов
- тут
await
блок цикла? Илиi
продолжайте увеличиваться, покаawait
ing?
"блок" - не то слово, Но да,я не продолжает увеличиваться во время ожидания. Вместо этого выполнение возвращается туда, где async
функция была вызвана, предоставляя обещание как возвращаемое значение, продолжая остальную часть кода, который следует после вызова функции, пока стек кода не был опорожнить. Затем, когда ожидание закончено, состояние функции восстанавливается, и выполнение продолжается внутри этой функции. Всякий раз, когда эта функция возвращается (завершается), соответствующее обещание, которое было возвращено ранее, разрешается.
- порядок
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);
});
}