顺序执行许多承诺(概念)

时间:2019-01-03 14:42:21

标签: javascript node.js asynchronous promise axios

(我的目标是阐明我对此问题的概念,而不是代码)

我想按顺序执行一个promise数组,但是nodeJS抛出了一个关于许多并行执行的promise的奇怪错误(因为我将数组限制为20个promise和Works,50个promise和works,但是9000个promise和爆炸。)

  • 我知道我们有一些解决方案,例如array.reduce(),循环等
  • 我了解诺言状态(我的数组最初有未完成的诺言)

我的问题:我可以执行20个诺言,然后再执行20个诺言,依此类推,但是... 如果我按顺序执行我的诺言,nodeJS必须执行9k个诺言没有问题吗?我的观念不好吗?我的代码不正确?

(令人怀疑,因为nodeJS在开始兑现承诺之前要等待一段时间)

我的情况:我尝试下载9k +图像(使用axios),然后保存每个图像,然后依次等待5秒钟。 [下载1张图像,保存该图像,等待5秒钟,然后下载下一张图像,保存..,等待...,等等。]可能吗?

1 个答案:

答案 0 :(得分:1)

我本来会使用worker pool之类的东西,而不是每次都以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')
})