如何在保存之前等待创建流的循环完成?
How to wait for a loop creating streams to finish before saving?
我不知道循环何时结束,
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
,但是您需要将每个 "files" 包装在一个 Promise 中,并且 return 根据每个 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
});
});
这不涉及额外的依赖项,但是您可以交替使用 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)
});
}
);
});
所以他们看起来很相似,基本上他们在做同样的事情。在每种情况下,"loop" 现在是一个 .map()
,它传入当前文件名作为参数,return 是一个转换后的响应数组,在本例中是 base64
函数。他们的关键是 resolve
或 callback
基本上控制着事情发生的时间。
在使用 Promise.all
的情况下,.map()
是数组上的基本 JavaScript .map()
函数,本质上是 returning 一个 "array of Promise" 都实现了 reject
和 resolve
函数,然后由流中的相应处理程序调用。
此处 "Promises" 全部执行,return 在 Promise.all
中产生结果,并将输出数组传递给 .then()
块,其中包含内容并且可以然后根据情况将您的方法传递给 update/create。
在 async.map
示例中,它使用了一个 callback
参数,该参数再次提供给流上的事件处理程序。以完全相同的方式,最后一个块接收输出或错误,并可以再次传递给您的方法以保留数据。
调用的实际执行略有不同,但本质上都是将我们"signal"输出完成的原理应用到提供"loop"的机制上,这样我们就知道什么时候"all" 已完成。
我不知道循环何时结束,
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
,但是您需要将每个 "files" 包装在一个 Promise 中,并且 return 根据每个 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
});
});
这不涉及额外的依赖项,但是您可以交替使用 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)
});
}
);
});
所以他们看起来很相似,基本上他们在做同样的事情。在每种情况下,"loop" 现在是一个 .map()
,它传入当前文件名作为参数,return 是一个转换后的响应数组,在本例中是 base64
函数。他们的关键是 resolve
或 callback
基本上控制着事情发生的时间。
在使用 Promise.all
的情况下,.map()
是数组上的基本 JavaScript .map()
函数,本质上是 returning 一个 "array of Promise" 都实现了 reject
和 resolve
函数,然后由流中的相应处理程序调用。
此处 "Promises" 全部执行,return 在 Promise.all
中产生结果,并将输出数组传递给 .then()
块,其中包含内容并且可以然后根据情况将您的方法传递给 update/create。
在 async.map
示例中,它使用了一个 callback
参数,该参数再次提供给流上的事件处理程序。以完全相同的方式,最后一个块接收输出或错误,并可以再次传递给您的方法以保留数据。
调用的实际执行略有不同,但本质上都是将我们"signal"输出完成的原理应用到提供"loop"的机制上,这样我们就知道什么时候"all" 已完成。