如何等待循环创buildstream保存之前完成?

我知道循环何时完成,

app.post('/api/books', upload.array('images'), function(req, res) { let book = req.body.book; let arr = []; // GridFS get connection with DB var gfs = gridfsstream(conn.db); var writestream; for (i = 0; i < req.files.length; i++) { writestream = gfs.createWriteStream({ filename: req.files[i].originalname }); fs.createReadStream('uploads/' + req.files[i].filename).pipe(writestream); writestream.on("close", function(file) { console.log(file.filename + "stored successfully into mongodb using gridfs"); }); writestream.on("error", function(file) { console.log(file.filename + "not stored into mongodb using gridfs"); }); base64(writestream.name, function(response) { arr.push(response); }); } book.images = arr; Book.addBook(book, function(err, book) { if (err) { throw err; } res.json(book); }); }); 

问题是:当我这样做时,数组arr是空的

 book.images = arr 

我需要等待for循环完成,但我怎么做?

我知道这个工程,因为我已经把一个console.log()并正常工作

 base64(writestream.name, function(response) { arr.push(response); }); 

可能最好在这里使用Promise.all ,但是你需要将每个“文件”包装在一个Promise中,并根据每个writeStream完成时间或错误情况返回parsing:

 app.post('/api/books', upload.array('images'), function(req,res) { let book = req.body.book; var gfs = gridfsstream(conn.db); Promise.all( req.files.map(function(file) => { return new Promise(function(resolve,reject) { var writestream = gfs.createWriteStream({ filename: file.originalname }); fs.createReadStream('uploads/'+file.filename).pipe(writestream); writestream.on("error",reject); writestream.on("close",function() { base64(writestream.name, function(response) { resolve(response); }); }); }) }) ) .then(function(images) { book.images = images; Book.addBook(book,function(err,book) { if (err) throw err; // or whatever res.json(book) }); }) .catch(function(err) => { // Deal with errors }); }); 

这不涉及额外的依赖关系,但是您可以交替使用async.map作为附加依赖项:

 app.post('/api/books', upload.array('images'), function(req,res) { let book = req.body.book; var gfs = gridfsstream(conn.db); async.map( req.files, function(file,callback) { var writestream = gfs.createWriteStream({ filename: file.originalname }); fs.createReadStream('uploads/'+file.filename).pipe(writestream); writestream.on("error",callback); writestream.on("close",function() { base64(writestream.name, function(response) { callback(null,response); }); }); }, function(err,images) { if (err) throw err; book.images = images; Book.addBook(book,function(err,book) { if (err) throw err; // or whatever res.json(book) }); } ); }); 

所以他们看起来很相似,基本上他们也在做同样的事情。 在每种情况下,“循环”现在是一个.map() ,它将当前文件名作为参数传入,并返回转换响应的数组,在这种情况下,它是base64函数的输出。 他们关键在于resolvecallback基本上是在事情发生的时候控制。

在使用Promise.all的情况下, .map()是数组上的基本JavaScript .map()函数,它基本上返回一个“ Promise数组”,它们都实现了rejectresolve函数,然后由stream中的相应处理程序。

在这里,“Promises”全部执行并返回Promise.all结果,并将输出数组传递给具有.then()的块,然后传递给你的方法来更新/创build。

async.map示例中,它使用一个callback参数,该参数再次提供给stream上的事件处理程序。 完全相同的方式,最后的块接收输出或错误,并可以再次传递给你的方法来坚持数据。

调用的实际执行有一些细微的差别,但两者实质上都是将我们“输出”输出完成的原理应用于提供“循环”的机制,以便我们知道何时“全部”完成。