#javascript #asynchronous #async-await
#javascript #асинхронный #асинхронный-ожидающий
Вопрос:
Я бы хотел, чтобы данные внутри Promise.all
были разрешены до того, как я фактически выполню разрушение массива:
const function = async (one, two) => {
const [_one, _two] = await Promise.all([
one.map(translate), // translate is async
two.map(translate),
])
console.log(_one, _two)
}
const translate = async (data) => getTranslation(data) // getTranslation is async, an API call
Прямо сейчас, console.log
Promise
вместо фактических данных я получаю
Комментарии:
1. почему вы используете
await
функцию, которая уже возвращает обещание2. Какую строку ты имеешь в виду, 2-я? Я следил: dalejefferson.com/articles /…
3.
Promise.all()
ожидает итерациюPromise
s, а не массив массивов (сPromise
s)4.
translate
является asyn однако вы не вводите его результатPromise.all
— вы вводите результатone.map(translate)
, который является массивом , а не обещанием.5. @Eldar это приводит к совершенно другим результатам.
Ответ №1:
one.map(translate)
возвращает массив обещаний. Вы должны использовать Promise.all
, чтобы преобразовать его в обещание.
one // Element[]
one.map(translate) // Promise<Element>[]
Promise.all(one.map(translate)) // Promise<Element[]>
В заключение, вы должны использовать Promise.all
дважды:
const function = async (one, two) => {
const [_one, _two] = await Promise.all([
Promise.all(one.map(translate)), // <<
Promise.all(two.map(translate)), // <<
])
console.log(_one, _two)
}
Комментарии:
1. интересная идея.
Ответ №2:
Проблема в том, что Promise.all
ожидается массив обещаний. Однако вы предоставляете ему массив всего из двух массивов, каждый из которых содержит обещания. Метод не является рекурсивным.
Вам необходимо изменить свой код, чтобы ожидать только содержимое массивов:
const fn = async (one, two) => {
const [_one, _two] = [
await Promise.all(one.map(translate)),
await Promise.all(two.map(translate))
];
console.log(_one, _two);
}
const translate = async (data) => getTranslation(data);
//mock an API call
function getTranslation(data) {
return Promise.resolve(`${data}-translated`);
}
fn(["a", "b"], ["x", "y"]);
Вы можете обобщить этот код для обработки многих массивов, которые будут отображаться асинхронно с помощью такого рода функций
const fn = async (one, two) => {
const [_one, _two] = await asyncMapMultiple(translate, [one, two]);
console.log(_one, _two);
}
const translate = async (data) => getTranslation(data);
//mock an API call
function getTranslation(data) {
return Promise.resolve(`${data}-translated`);
}
async function asyncMapMultiple(asyncMapper, arrays) {
return Promise.all( //produce a promise that resolves when everything is finished
arrays.map(arr => Promise.all(arr.map(asyncMapper))) //map each array asynchronously
);
}
fn(["a", "b"], ["x", "y"]);
Ответ №3:
Promise.all
ожидайте массив обещаний, а не обычный массив массивов. Это должен быть плоский массив, а не вложенный.
Что вы можете сделать, так это иметь 2 Promise.all()
(если вы хотите разделить one
и two
):
const function = async (one, two) => {
const _one = await Promise.all(one.map(translate));
const _two = await Promise.all(two.map(translate));
console.log(_one, _two)
}
Если вы действительно хотите объединить их и использовать уничтожение массива, вам сначала нужно их сгладить и объединить,
await Promise.all([...one.map(translate), ...two.map(translate)]);
однако это вызовет некоторые проблемы, когда вы захотите разделить данные, поскольку вы не уверены, сколько массивов будет возвращено, если у вас нет какого-либо ключа для каждого результата.