#javascript #asynchronous #async-await #promise
Вопрос:
wait
функция используется в качестве функции сна, fn
функция принимает массив (элементы), регистрирует каждый элемент и отключается на секунду, прежде чем регистрировать следующий элемент.
const wait = async(time) => {
return new Promise((resolve) => setTimeout(resolve, time))
}
const fn = async(items) => {
for (item of items) {
await wait(1000)
console.log(item)
}
}
const exeAll = async() => {
Promise.all([
fn(['A1', 'A2']),
fn(['B1', 'B2']),
])
}
exeAll()
Проблема заключается в результате, предоставляемом exeAll
функцией, которая выводит:
B1
A2
B2
B2
Но я думаю, что на нем должно быть напечатано что-то вроде:
A1
B1
A2
B2
A1 вообще не отображается при выполнении приведенного выше кода. Кто-нибудь может объяснить, почему ?
Комментарии:
1. Если вы
await
звонитеfn()
поPromise.all()
вызову, он работает именно так, как вы ожидаете.2. и B2 всегда регистрируется дважды в конце.
3. Не нужно
exeAll
быть асинхронным.4. Я не хочу, чтобы
await
они, ожидая их, заставляли их выполнять все по порядку. что бы напечатать: A1 A2 B1 B25. Я удалил
async
ключевое слово из функции exeAll, и ничего не изменилось, проблема всегда есть.A1
не печатается иB2
печатается дважды.
Ответ №1:
for (item of items) {
создаст неявную глобальную переменную item
, т. е. несколько вызовов fn
будут мешать друг другу, перезаписывая item
. Правильно объявите переменную, и она будет работать так, как ожидалось:
const wait = async(time) => {
return new Promise((resolve) => setTimeout(resolve, time))
}
const fn = async(items) => {
for (let item of items) {
// ^^^^
await wait(1000)
console.log(item)
}
}
const exeAll = async() => {
Promise.all([
fn(['A1', 'A2']),
fn(['B1', 'B2']),
])
}
exeAll()
Мы можем добавить дополнительные записи fn
, чтобы узнать, что происходит, когда в вашем случае:
const wait = async(time) => {
return new Promise((resolve) => setTimeout(resolve, time))
}
let counter = 0;
const fn = async(items) => {
const c = counter ;
console.log(`enter fn call #${c}`);
for (item of items) {
console.log(`fn call #${c} sets item <-`, item);
await wait(1000)
console.log(`fn call #${c} reads item ->`, item);
console.log(item)
}
}
const exeAll = async() => {
Promise.all([
fn(['A1', 'A2']),
fn(['B1', 'B2']),
])
}
exeAll()
Строгий режим ( "use strict";
) поймал бы эту ошибку, потому что назначение необъявленной переменной приводит к ошибке.
Комментарии:
1. Строгий режим (
"use strict";
) поймал бы это, потому что присвоение необъявленным переменным приводит к ошибке 😉2. Точно. «строгий режим» — это первое, что пришло мне в голову, когда я впервые увидел ваш ответ.