这一节主要是为了阐述一种特定任务的解决办法:并发任务中拥有一些串行执行的子任务——假设你要对3个不同的文件执行A、B、C、D操作,这3个文件的处理顺序没有要求,但是A、B、C、D四步操作必须按照既定顺序执行。我们可以按照下面的思路来处理这个问题:
- 创建一个promise链
- 每一个promise都代表A、B、C、D中的一个操作
- 使用
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.txt
、b.txt
、c.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库中的内容。