Используйте асинхронное ожидание с массивом.карта


учитывая следующий код:

var arr = [1,2,3,4,5];

var results: number[] = await arr.map(async (item): Promise<number> => {
        await callAsynchronousOperation(item);
        return item + 1;
    });

что приводит к следующей ошибке:

TS2322: тип 'Promise[]' не может быть присвоен типу 'number[]'. Тип ' Promise не может быть присвоен типу 'number'.

как я могу это исправить? Как я могу сделать async await и Array.map работать вместе?

4 91

4 ответа:

проблема здесь в том, что вы пытаетесь await массив. Это не то, что вы ожидаете.

когда объект передается в await - это не обещание, await просто возвращает значение as-is немедленно вместо того, чтобы пытаться решить его. Так как вы прошли await массив (объектов Promise) здесь вместо Promise, значение, возвращаемое await-это просто массив, который имеет тип Promise<number>[].

что вам нужно сделать здесь-это вызов Promise.all на массив, возвращаемый map чтобы преобразовать его в одно обещание до awaiting его.

по словам MDN docs for Promise.all:

The Promise.all(iterable) метод возвращает обещание, которое устраняет когда все обещания в качестве аргумента при обходе решили, или отвергает с причиной первого пропущенного обещания то, что отвергает.

так что в вашем случае:

var arr = [1, 2, 3, 4, 5];

var results: number[] = await Promise.all(arr.map(async (item): Promise<number> => {
    await callAsynchronousOperation(item);
    return item + 1;
}));

это позволит решить конкретные ошибка, с которой вы столкнулись здесь.

есть еще одно решение для этого, если вы не используете родные обещания, но Bluebird.

вы также можете попробовать использовать обещание.map (), перемешивание массива.карта и обещание.все

в случае:

  var arr = [1,2,3,4,5];

  var results: number[] = await Promise.map(arr, async (item): Promise<number> => {
    await callAsynchronousOperation(item);
    return item + 1;
  });

Если вы сопоставляете массив обещаний, вы можете затем разрешить их все в массив чисел. Смотрите обещание.все.

Я бы рекомендовал использовать Promise.все, как упоминалось выше, но если вы действительно хотите избежать этого подхода, вы можете сделать for или любой другой цикл:

const arr = [1,2,3,4,5];
let resultingArr = [];
for (let i in arr){
  await callAsynchronousOperation(i);
  resultingArr.push(i + 1)
}