Выполнить много обещаний последовательно (Концепция) - PullRequest
0 голосов
/ 03 января 2019

(Моя цель - разъяснить мою концепцию о проблеме, а не код)

Я хочу выполнить массив обещаний последовательно, но nodeJS выдает странную ошибку о многих обещаниях, выполняемых параллельно (потому что я ограничил этот массив до 20 обещаний и работ, 50 обещаний и работ, но 9000 обещаний и взрыв) ..)

  • Я знаю, что у нас есть некоторые решения, такие как array.reduce (), loop и т. Д.
  • Я знаю о состояниях обещаний (у моего массива изначально есть ожидающие обещания)

Мой вопрос: я могу выполнить 20 обещаний, затем еще 20 обещаний и т. Д., Но ... Если я выполняю свои обещания последовательно, nodeJS должен выполнить обещания 9k без проблем? У меня плохая концепция? Мой код неверен?

(Я сомневаюсь, потому что nodeJS подождет некоторое время, прежде чем начать выполнять обещания)

Мой случай: я пытаюсь загрузить 9k + изображений (с axios), затем сохранить каждое из них и затем подождать 5 секунд последовательно. [загрузить 1 изображение, сохранить это изображение, подождать 5 секунд, затем загрузить следующее изображение, сохранить .., подождать ... и т. д.] Возможно?

1 Ответ

0 голосов
/ 03 января 2019

Я бы использовал что-то вроде рабочий пул вместо того, чтобы каждый раз выполнять вещи по 20, вы всегда будете ждать окончания последнего, прежде чем начнете следующие 20 партий, вместо этогоВы должны установить ограничение на количество непрерывных загрузок, которое вы хотите сделать, чтобы у вас было не более 20 обещаний и не длинная цепочка из 9000

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

Так что с нулевыми зависимостями я бы сделал что-то вроде этого:

const sleep = n => new Promise(rs => setTimeout(rs, 1000))

async function sequentialDownload(iterator) {
  for (let [index, url] of iterator) {
    // figure out where to save the file
    const path = path.resolve(__dirname, 'images', index + '.jpg')
    // download all images as a stream
    const res = await axios.get(index, { responseType: 'stream' })

    // pipe the stream to disc
    const writer = fs.createWriteStream(path)
    res.data.pipe(writer)

    // wait for the download to complete
    await new Promise(resolve => writer.on('finish', resolve))
    // wait a extra 5 sec
    await sleep(5000)
  }
}

const arr = [url1, url2, url3] // to be downloaded
const workers = new Array(20) // create 20 "workers"
  .fill(arr.entries()) // fill it with same iterator
  .map(sequentialDownload) // start working

Promise.all(workers).then(() => {
  console.log('done downloading everything')
})
...