Async/Ожидание внутри массива # map()
Я получаю ошибку времени компиляции с помощью этого кода:
const someFunction = async (myArray) => {
return myArray.map(myValue => {
return {
id: "my_id",
myValue: await service.getByValue(myValue);
}
});
};
Сообщение об ошибке:
Ожидание - это зарезервированное слово
Почему я не могу использовать его так?
Я также пробовал другой путь, но он дает мне такую же ошибку:
const someFunction = async (myArray) => {
return myArray.map(myValue => {
const myNewValue = await service.getByValue(myValue);
return {
id: "my_id",
myValue: myNewValue
}
});
};
Ответы
Ответ 1
Вы не можете сделать это, как вы себе представляете, потому что вы не можете использовать await
, если он не находится непосредственно внутри функции async
.
Разумной задачей здесь было бы сделать функцию, переданную в map
асинхронной. Это означает, что map
вернет массив из promises. Затем мы можем использовать Promise.all
для получения результата, когда возвращается все promises. Поскольку Promise.all
сам возвращает обещание, внешняя функция не должна быть async
.
const someFunction = (myArray) => {
const promises = myArray.map(async (myValue) => {
return {
id: "my_id",
myValue: await service.getByValue(myValue)
}
});
return Promise.all(promises);
}
Ответ 2
Это потому, что функция в map
не является асинхронной, поэтому вы не можете ожидать в ней оператора return. Компилируется с этой модификацией:
const someFunction = async (myArray) => {
return myArray.map(async (myValue) => { // <-- note the 'async' on this line
return {
id: "my_id",
myValue: await service.getByValue(myValue)
}
});
};
Попробуйте в Babel REPL
Поэтому… невозможно дать рекомендацию, не видя остальную часть вашего приложения, но в зависимости от того, что вы пытаетесь сделать, либо сделайте внутреннюю функцию асинхронной, либо попробуйте придумать другую архитектуру для этого блока.
Обновление: мы могли бы получить на высшем уровне ждать один день: https://github.com/MylesBorins/proposal-top-level-await
Ответ 3
Если вы хотите запустить карту с функцией асинхронного отображения, вы можете использовать следующий код:
const resultArray = await Promise.all(inputArray.map(async (i) => someAsyncFunction(i)));
Как это работает:
inputArray.map(async ...)
возвращает массив обещаний - по одному для каждого значения в inputArray
.
- Помещение
Promise.all()
вокруг массива обещаний превращает его в одно обещание.
- Одно обещание из
Promise.all()
возвращает массив значений - каждое обещание каждого разрешения принимает одно значение.
- Мы помещаем
await
перед Promise.all()
, чтобы дождаться разрешения объединенного обещания и сохранить массив разрешенных вложенных обещаний в переменную resultArray
.
В конце мы получаем одно выходное значение в resultArray
для каждого элемента в inputArray
, сопоставленное через функцию someAsyncFunction
. Нам нужно дождаться разрешения всех асинхронных функций, прежде чем станет доступен результат.