Рубрики
Без рубрики

Как использовать асинхронность и ожидание с помощью Array.prototype.map()

Использование async/await в сочетании с map() может быть немного сложным. Узнайте, как это сделать.

Вы хотите выполнить асинхронную функцию внутри вызова map() , выполнить операцию над каждым элементом массива и получить результаты обратно.

Как вы можете это сделать?

Это правильный синтаксис:

const list = [1, 2, 3, 4, 5] //...an array filled with values

const functionThatReturnsAPromise = item => { //a function that returns a promise
  return Promise.resolve('ok')
}

const doSomethingAsync = async item => {
  return functionThatReturnsAPromise(item)
}

const getData = async () => {
  return Promise.all(list.map(item => doSomethingAsync(item)))
}

getData().then(data => {
  console.log(data)
})

Главное, на что следует обратить внимание, – это использование Promise.all() , которое разрешается, когда все его обещания выполняются.

list.map() возвращает список обещаний, поэтому в результате мы получим значение, когда все, что мы запустили, будет выполнено.

Помните, что мы должны обернуть любой код, вызывающий await , в функцию async .

Подробнее об обещаниях читайте в статье “Обещания”, а также в руководстве по асинхронности/ожиданию.

Может быть трудно визуализировать пример с этими именами функций-заполнителей, поэтому простым примером использования этой техники является функция удаления данных Prisma, которую я написал для клона Twitter, чтобы сначала удалить твиты, а затем пользователей:

export const clearData = async (prisma) => {
  const users = await prisma.user.findMany({})
  const tweets = await prisma.tweet.findMany({})

  const deleteUser = async (user) => {
    return await prisma.user.delete({
      where: { id: user.id }
    })
  }
  const deleteTweet = async (tweet) => {
    return await prisma.tweet.delete({
      where: { id: tweet.id }
    })
  }

  const deleteTweets = async () => {
    return Promise.all(tweets.map((tweet) => deleteTweet(tweet)))
  }

  const deleteUsers = async () => {
    return Promise.all(users.map((user) => deleteUser(user)))
  }

  deleteTweets().then(() => {
    deleteUsers()
  })
}

Технически это можно было бы гораздо проще резюмировать следующим образом

export const clearData = async (prisma) => {
  await prisma.tweet.deleteMany({})
  await prisma.user.deleteMany({})
}

но приведенный выше код также действителен и показывает, как использовать обещания в Array.map() , в чем и заключается суть этого урока.

Оригинал: “https://flaviocopes.com/javascript-async-await-array-map/”