组合promise对象

这一节主要是为了阐述一种特定任务的解决办法:并发任务中拥有一些串行执行的子任务——假设你要对3个不同的文件执行A、B、C、D操作,这3个文件的处理顺序没有要求,但是A、B、C、D四步操作必须按照既定顺序执行。我们可以按照下面的思路来处理这个问题:

  1. 创建一个promise链
  2. 每一个promise都代表A、B、C、D中的一个操作
  3. 使用Promise.all来并行运行所有的promise链
const files = ['a.txt', 'b.txt', 'c.txt']

function performInOrder(file) {
  const promise = taskA(file)
    .then(taskB)
    .then(taskC)
    .then(taskD)
  return promise
}

const operations = files.map(performInOrder)
const result = Promise.all(operations)

result.then(d => console.log(d)).catch(e => console.log(e))

下面是一份真实可运行的代码,处理了a.txtb.txtc.txt三份文件:

code/promises/read-write-multiple-files/main.js

const fs = require('fs')
const util = require('util')

const readFile = util.promisify(fs.readFile)
const writeFile = util.promisify(fs.writeFile)
const copyFile = file => content => writeFile(file + '-copy.txt', content)
const replaceContent = input => Promise.resolve(input.replace(/-/g, 'zzzz'))

const processEachInOrder = file => {
  return readFile(file, 'utf-8')
    .then(replaceContent)
    .then(copyFile(file))
}

const files = ['./a.txt', './b.txt', './c.txt']
const promises = files.map(processEachInOrder)
Promise.all(promises)
  .then(d => console.log(d))
  .catch(e => console.log(e))

值得注意的是,如果输入很大,这种方式会给CPU带来很大的压力。比较好的做法是,限制并发任务的数量。async库中有一个queue方法可以限制每次并行执行的异步任务的数量,从而降低CPU的负担。接下来的章节,我们会探讨一些async库中的内容。

用户头像
登录后发表评论