javascript - Resolve promises one after another (i.e. in sequence)? -
consider following code reads array of files in serial/sequential manner. readfiles
returns promise, resolved once files have been read in sequence.
var q = require("q"); var readfile = function(file) { ... // returns promise. }; var readfiles = function(files) { var deferred = q.defer(); var readsequential = function(index) { if (index >= files.length) { deferred.resolve(); } else { readfile(files[index]).then(function() { readsequential(index + 1); }); } }; readsequential(0); // start! return deferred.promise; };
the code above code works, don't having recursion things occur sequentially. there simpler way code can re-written don't have use weird readsequential
function?
originally tried use q.all
, caused of readfile
calls happen concurrently, not want:
var readfiles = function(files) { return q.all(files.map(function(file) { return readfile(file); })); };
update 2017: use async function if environment supports it:
async function readfiles(files) { for(const file of files) { await readfile(file); } };
if you'd like, can defer reading files until need them using async generator (if environment supports it):
async function* readfiles(files) { for(const file of files) { yield await readfile(file); } };
update: in second thought - might use loop instead:
var readfiles = function(files) { var p = q(); // promise.resolve() without q files.foreach(function(file){ p = p.then(function(){ return readfile(file); }); // or .bind }); return p; };
or more compactly, reduce:
var readfiles = function(files) { return files.reduce(function(p, file) { return p.then(function(){ return readfile(file); }); },q()); // initial };
in other promise libraries (like when , bluebird) have utility methods this.
for example, bluebird be:
var promise = require("bluebird"); var fs = promise.promisifyall(require("fs")); var readall = promise.resolve(files).map(fs.readfileasync,{concurrency: 1 }); // if order matters, can use promise.each instead , omit concurrency param readall.then(function(allfilecontents){ // stuff read files. });
in q, have can - can shorten array.prototype.reduce
bit , extract generic method.
if can use q.async
(that you're on node) things better:
q.spawn(function* () { var results = []; for(var = 0;i < files.length; i++){ results.push(yield readfile(files[i])); } console.log(results); });
just remember run node --harmony
and remember it's experimental atm.
Comments
Post a Comment