一个接一个地(即按顺序)解决承诺? [英] Resolve promises one after another (i.e. in sequence)?
问题描述
考虑以下以串行/顺序方式读取文件数组的代码.readFiles
返回一个承诺,只有在按顺序读取所有文件后才会解决.
Consider the following code that reads an array of files in a serial/sequential manner. readFiles
returns a promise, which is resolved only once all files have been read in sequence.
var readFile = function(file) {
... // Returns a promise.
};
var readFiles = function(files) {
return new Promise((resolve, reject) => {
var readSequential = function(index) {
if (index >= files.length) {
resolve();
} else {
readFile(files[index]).then(function() {
readSequential(index + 1);
}).catch(reject);
}
};
readSequential(0); // Start with the first file!
});
};
上面的代码有效,但我不喜欢为了顺序发生的事情而进行递归.有没有更简单的方法可以重写这段代码,这样我就不必使用我奇怪的 readSequential
函数?
The above code works, but I don't like having to do recursion for things to occur sequentially. Is there a simpler way that this code can be re-written so that I don't have to use my weird readSequential
function?
最初我尝试使用 Promise.all
,但这导致所有 readFile
调用同时发生,这不是我想要:
Originally I tried to use Promise.all
, but that caused all of the readFile
calls to happen concurrently, which is not what I want:
var readFiles = function(files) {
return Promise.all(files.map(function(file) {
return readFile(file);
}));
};
推荐答案
Update 2017:如果环境支持,我会使用异步函数:
Update 2017: I would use an async function if the environment supports it:
async function readFiles(files) {
for(const file of files) {
await readFile(file);
}
};
如果您愿意,可以使用异步生成器(如果您的环境支持)推迟读取文件,直到您需要它们:
If you'd like, you can defer reading the files until you need them using an async generator (if your environment supports it):
async function* readFiles(files) {
for(const file of files) {
yield await readFile(file);
}
};
<小时>
更新:再想一想 - 我可能会改用 for 循环:
Update: In second thought - I might use a for loop instead:
var readFiles = function(files) {
var p = Promise.resolve(); // Q() in q
files.forEach(file =>
p = p.then(() => readFile(file));
);
return p;
};
或者更简洁,使用reduce:
Or more compactly, with reduce:
var readFiles = function(files) {
return files.reduce((p, file) => {
return p.then(() => readFile(file));
}, Promise.resolve()); // initial
};
在其他 Promise 库(例如 when 和 Bluebird)中,您有用于此的实用方法.
In other promise libraries (like when and Bluebird) you have utility methods for this.
例如,Bluebird 将是:
For example, Bluebird would be:
var Promise = require("bluebird");
var fs = Promise.promisifyAll(require("fs"));
var readAll = Promise.resolve(files).map(fs.readFileAsync,{concurrency: 1 });
// if the order matters, you can use Promise.each instead and omit concurrency param
readAll.then(function(allFileContents){
// do stuff to read files.
});
尽管今天确实没有理由不使用异步等待.
Although there is really no reason not to use async await today.
这篇关于一个接一个地(即按顺序)解决承诺?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!