我知道循环何时完成,
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);
});
答案 0 :(得分:3)
可能最好在这里使用default style,但是您需要将每个“文件”包装在Promise中并根据每个文件中的writeStream
何时完成或错误返回解决:
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
});
});
这不涉及其他依赖项,但您可以使用Promise.all
作为附加依赖项:
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)
});
}
);
});
所以他们看起来非常相似,基本上他们也在做同样的事情。在每种情况下,“循环”现在是async.map
,它将当前文件名作为参数传递,并返回已转换响应的数组,在本例中是base64
函数的输出。它们的关键在于resolve
或callback
基本上可以控制事情的发生。
在使用.map()
的情况下,Promise.all
是数组上的基本JavaScript .map()
函数,它实际上返回了一个“.map()
数组”,它们都实现了reject
和resolve
函数,然后由流上的相应处理程序调用。
这里的“Promises”全部在Promise内执行并返回结果,并将输出数组传递给具有.then()
的块,该块具有内容,然后可以传递给您的方法以更新/可能是这样的。
在Promise.all
示例中,这使用了callback
参数,该参数再次提供给流上的事件处理程序。以完全相同的方式,最后一个块接收输出或错误,并且可以再次传递给您的方法以持久保存数据。
实际执行调用之间存在细微差别,但两者基本上都应用了我们“信号”输出完成的相同原则到提供“循环”的机制,以便我们知道“所有”何时完成。