Как выполнить действие после завершения вложенных выборок? - PullRequest
3 голосов
/ 25 июня 2019

Приведенный ниже код извлекает массив из API, затем для каждого элемента этого массива извлекает дополнительные данные.

fetch('https://reqres.in/api/users')
  .then(r => r.json()).then(r => {
    r.data.forEach(x => {
      fetch('https://reqres.in/api/users')
        .then(r => r.json()).then(r => {
          r.data.forEach(x => console.log(x.id))
        })
    })
  })

Мне нужно выполнить какое-то действие с данными после их полного извлечения. Как это сделать?

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

a = fetch('https://reqres.in/api/users')
b = fetch('https://reqres.in/api/users')
Promise.all([a, b]).then(x => console.log('all resolved here'))

но то, что передается в Promise.all(), неизвестно при запуске сценария.

Ответы [ 3 ]

2 голосов
/ 25 июня 2019

Вы можете сделать массив обещаний, используя Array.map:

const allPromises = r.data.map(x => {
  return fetch('https://reqres.in/api/users/' + x)
    .then(r => r.json())
});

Promise.all(allPromises).then(data => console.log('All data is loaded', data))
2 голосов
/ 25 июня 2019

... но то, что передается в Promise.all (), неизвестно при запуске сценария.

Все в порядке, вы можете использовать map вместо forEach, а затем дождаться результата:

fetch('https://reqres.in/api/users')
  .then(r => r.json()).then(r =>
    Promise.all(r.data.map(x =>
      fetch('https://reqres.in/api/users') // (presumably there's some parameter here, you're not just repeating the same call...)
        .then(r => r.json())
        .then(r => {
          r.data.forEach(x => console.log(x.id))
        })
    ))
  );

Цепочка вышеуказанных возвратов не будет исчерпана, пока все обещания, созданные в map, не будут решены или одно из них не отклонено.

1 голос
/ 25 июня 2019

Может быть, это решение проблемы, но кажется, что с вашим подходом что-то не так.

fetch('https://reqres.in/api/users')
  .then(r => r.json()).then(r => {
    return Promise.all(r.data.map(x => {
      return fetch('https://reqres.in/api/users')
        .then(r => r.json()).then(r => {
          r.data.forEach(x => console.log(x.id))
        })
      )
    })
  })

Другими словами, вы можете использовать вложенный Promise.all и вернуть его в результате выполнениявнутренний код ваших then s.И еще одно важное замечание: вы должны использовать map, а не forEach для итеративных асинхронных вызовов.

...