Использование async/await c Array.map в TypeScript: решение ошибок

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

JS
Скопировать код
// Функция для параллельной обработки набора асинхронных задач
async function asyncMap(array, asyncFn) {
  return Promise.all(array.map(item => asyncFn(item)));
}

// Пример (Простые вычисления) 🧮:
const results = await asyncMap([1, 2, 3], async num => {
  return num * 2; // Асинхронное действие — это удвоение чисел
});
console.log(results); // Вывод: [2, 4, 6]

При использовании Array.map вы стартуете асинхронные операции одновременно. Далее, с помощью Promise.all, вы ожидаете их завершения. Функция asyncMap максимально прозрачна. В представленном примере мы удвоили числа для иллюстрации.

Кинга Идем в IT: пошаговый план для смены профессии

Понимание комбинаторов Promise: Фантастическая четвёрка

Если перед вами встаёт задача работать с множеством промисов, изучите следующие комбинаторы Promise:

  1. Promise.all: Ждёт выполнения всех промисов.
  2. Promise.allSettled: Поддерживает обработку успешно завершившихся и с ошибкой операций.
  3. Promise.any: Отмечает первый успешно выполненный промис.
  4. Promise.race: Принцип «Кто быстрее выполнился (или "упал") — тот и победил».

Чаще всего вы будете выбирать Promise.all, но в ситуациях, когда вам важно знать результат каждой операции, независимо от её исхода, Promise.allSettled может быть полезным решением.

Обработка исключений: Будьте готовым ко всему

При выполнении асинхронного маппинга стоит обратить внимание на порядок выполнения. В этом поможет обработка исключений:

JS
Скопировать код
async function safeAsyncMap(array, asyncFn) {
  try {
    return await Promise.all(array.map(item => asyncFn(item)));
  } catch (error) {
    console.error("Обнаружено исключение:", error);
  }
}

Использование try/catch с await Promise.all поможет нам отслеживать исключения и обрабатывать их эффективно, не позволяя приложению аварийно завершиться.

Улучшение читабельности: Краткость — сестра таланта

Стрелочные функции в Array.map позволяют кратко и ясно описать асинхронные операции:

JS
Скопировать код
const asyncOperation = async item => {
  /* Здесь происходит магия асинхронной операции. */
};

const results = await Promise.all(items.map(asyncOperation));

С помощью стрелочных функций и async/await мы существенно упрощаем код и делаем его более наглядным.

TypeScript: Порядок в JavaScript

С использованием TypeScript вы получите типовую безопасность при работе с Array.map, что снижает вероятность ошибок и предупреждает возможные сбои в системе.

Визуализация

Представьте применение async/await с Array.map в виде группы фотографов (📸), которые одновременно фотографируют различные пейзажи 🏞️:

Markdown
Скопировать код
| Фотограф (📸) | Пейзаж (🏞️) | Действие       |
| ------------- | ------------ | -------------- |
| 📸 1          | 🏞️ A        | Фотографировать |
| 📸 2          | 🏞️ B        | Фотографировать |
| 📸 3          | 🏞️ C        | Фотографировать |

Процесс совпадает с логикой работы Array.map. Но вот проявка пленки — это асинхронный процесс!

JS
Скопировать код
let developedPhotos = await Promise.all(scenicSpots.map(async (spot) => {
    return await developPicture(spot);
}));

После проявки:

Markdown
Скопировать код
Результат проявки: [🖼️ A, 🖼️ B, 🖼️ C]

Фотографии делаются всеми сразу, но каждая проявляется поочерёдно. Именно так работает Array.map с async/await.

Тестирование асинхронного итерирования

Для тестирования асинхронного маппинга можно имитировать асинхронные процессы. Функция randomDelay отлично подойдёт для имитации сетевых задержек или задержек при файловых операциях на ввод/вывод:

JS
Скопировать код
function randomDelay(val) {
  return new Promise(resolve => setTimeout(() => {
    console.log(`Муторное ожидание? Вот здесь ваш ${val}.`);
    resolve(val);
  }, Math.random() * 1000));
}

let testResults = await Promise.all(arr.map(async n => await randomDelay(n)));

Тестирование с внесением искусственных задержек поможет удостовериться, что ваш код ведёт себя корректно в асинхронной среде.

Библиотека Bluebird: Незаменимый помощник Promise

Bluebird предлагает метод Promise.map(). Он регулирует параллелизм выполнения — отличное решение для конкретных задач:

JS
Скопировать код
let Bluebird = require('bluebird');  // Птицы ни при чём 🐦
let results = await Bluebird.map(array, asyncFn, { concurrency: 2 }); // Ограничение до 2 асинхронных вызовов одновременно

Такой подход позволяет более эффективно распределять системные ресурсы при большом количестве асинхронных операций.

Выжимка производительности

При работе с большим количеством данных или сложными операциями оптимизация становится важной:

  1. Ограничение параллелизма: Контролируйте количество одновременных операций, чтобы не перегружать цикл отслеживания событий.
  2. Блочная обработка: Разделяйте данные на части и обрабатывайте их по-отдельности.
  3. Избегание нецелесообразных вычислений: Не выполняйте операции, не влияющие на конечный результат.

Сохранение последовательности результатов: Всё в порядке

Используя Array.map и await с массивом промисов, вы получите результаты строго в том порядке, в котором они были инициированы:

JS
Скопировать код
const ids = [1, 2, 3]; // Исходная последовательность идентификаторов
const fetchDataForId = async id => { /* Подготовка важных данных */ };

const dataInOrder = await Promise.all(ids.map(fetchDataForId));

Даже если промисы разрешатся в разное время, dataInOrder сохранит исходную последовательность ids.

Полезные материалы

  1. Array.prototype.map() – JavaScript | MDN — страница MDN, где раскрыты тайны использования async/await с Array.map.
  2. Async/await — Детальное руководство от JavaScript Info о async/await, включая их работу с Array.map.
  3. JavaScript async and await in loops | Zell Liew — Zell Liew делится знаниями об особенностях использования async/await в циклах, включая map.
  4. javascript – Use async await with Array.map – Stack Overflow — Обсуждение на Stack Overflow по теме использования async/await с Array.map.
  5. How to use async functions with Array.map in Javascript – Advanced Web Machinery — Введение в последовательное выполнение асинхронных функций с Array.map.
  6. Await promise.all: How to use async/await with map and Promise.all – DEV Community — Обзор сообщества разработчиков по использованию асинхронных операций с map.