Node.js 如何将forEach与承诺结合起来
我正在做一个函数,将图像从输入文件字段上传到AWS,然后将图像URL和名称保存到mongoDB。我正在使用NodeJS和MongoDB。以下是我的例子:Node.js 如何将forEach与承诺结合起来,node.js,mongodb,promise,Node.js,Mongodb,Promise,我正在做一个函数,将图像从输入文件字段上传到AWS,然后将图像URL和名称保存到mongoDB。我正在使用NodeJS和MongoDB。以下是我的例子: uploadFile(req, res, next) { let files = req.files; let images = []; files.file.forEach((file) => { uploadToAWS(file.path, {}, function(err, img) { if (e
uploadFile(req, res, next) {
let files = req.files;
let images = [];
files.file.forEach((file) => {
uploadToAWS(file.path, {}, function(err, img) {
if (err) { throw err; }
// add path and name to images array
images.push({
path: img[0].url,
name: img[0].name,
});
});
});
// Here the promises should resolve and save to MongoDB the array images
},
不是每次循环遍历元素时都保存到数据库,我只是填充一个数组图像,然后将其保存到DB。为此,您希望使用而不是。这是因为您打算将一些值映射到基于每个值的承诺
return Promise.all(files.map((file) => {
// do some stuff with each file here
}));
完整示例如下所示:
uploadFile(req, res, next) {
let files = req.files;
let images = [];
const promises = files.file.map((file) => {
return uploadToAWS(file.path, {}).then((img) => {
// add path and name to images array
images.push({
path: img[0].url,
name: img[0].name,
});
});
});
// Here the promises should resolve and save to MongoDB the array images
Promise.all(promises).then(next);
}
注意,在这里,我假设uploadToAws能够返回一个承诺,因为这是实现这一点所必需的,否则纸牌屋的承诺就会崩溃。如果uploadToAws中没有内置的承诺支持,那么可以使用promisify实用程序,比如用适配器包装函数,该适配器将根据回调的结果为您创建承诺
资源
为此,您希望使用而不是。这是因为您打算将一些值映射到基于每个值的承诺
return Promise.all(files.map((file) => {
// do some stuff with each file here
}));
完整示例如下所示:
uploadFile(req, res, next) {
let files = req.files;
let images = [];
const promises = files.file.map((file) => {
return uploadToAWS(file.path, {}).then((img) => {
// add path and name to images array
images.push({
path: img[0].url,
name: img[0].name,
});
});
});
// Here the promises should resolve and save to MongoDB the array images
Promise.all(promises).then(next);
}
注意,在这里,我假设uploadToAws能够返回一个承诺,因为这是实现这一点所必需的,否则纸牌屋的承诺就会崩溃。如果uploadToAws中没有内置的承诺支持,那么可以使用promisify实用程序,比如用适配器包装函数,该适配器将根据回调的结果为您创建承诺
资源
你可以用蓝鸟来做你的
uploadToAWS返回承诺而不是接受回调您也可以在不使用promisify的情况下轻松地执行此操作,但它很有用,因为如果您要使用promise.all等,则使用返回承诺的函数要容易得多。如果您要使用接受回调的函数,我建议使用模块来管理控制流
当您承诺上传到AWS时,您将能够执行以下操作:
let promises = files.file.map(file => uploadToAWS(file.path, {}));
然后您将能够使用:
Promise.all(promises)
.then((imgs) => {
// everything succeeded
}).catch((error) => {
// there was an error
});
或者,如果您使用的是异步/等待:
try {
let imgs = await Promise.all(promises);
// everything succeeded
} catch (error) {
// there was an error
}
现在,无论何时你有IMG,它都是一个由uploadToAWS返回的对象数组,或者严格地说,是一个由uploadToAWS返回的承诺的解析值数组,在所有这些承诺都已解析之后
您可以使用该阵列创建另一个类似图像的阵列:
或:
取决于uploadToAWS实际返回的内容,因为您没有指定
但请记住,当您出现错误时,您需要通过删除已上载的不再需要的文件来恢复错误。您可以使用Bluebird's来进行恢复
uploadToAWS返回承诺而不是接受回调您也可以在不使用promisify的情况下轻松地执行此操作,但它很有用,因为如果您要使用promise.all等,则使用返回承诺的函数要容易得多。如果您要使用接受回调的函数,我建议使用模块来管理控制流
当您承诺上传到AWS时,您将能够执行以下操作:
let promises = files.file.map(file => uploadToAWS(file.path, {}));
然后您将能够使用:
Promise.all(promises)
.then((imgs) => {
// everything succeeded
}).catch((error) => {
// there was an error
});
或者,如果您使用的是异步/等待:
try {
let imgs = await Promise.all(promises);
// everything succeeded
} catch (error) {
// there was an error
}
现在,无论何时你有IMG,它都是一个由uploadToAWS返回的对象数组,或者严格地说,是一个由uploadToAWS返回的承诺的解析值数组,在所有这些承诺都已解析之后
您可以使用该阵列创建另一个类似图像的阵列:
或:
取决于uploadToAWS实际返回的内容,因为您没有指定
但是请记住,当您出现错误时,您需要通过删除已上载的不再需要的文件来恢复错误。这不是最好的办法。如果出现错误,S3上的孤立文件在数据库中没有任何引用。这不是最好的主意。如果出现错误,您将在S3上拥有孤立文件,而数据库中没有任何引用。使用.map的问题是,如果用户仅上载一个图像,则map失败,但如果用户上载多个.map工作正常。。。原因是对于多个文件,它发送一个对象数组,但是对于单个文件,它只发送一个对象。使用.map的问题是,如果用户只上载一个图像,则map失败,但是如果用户上载多个.map,则可以正常工作。。。原因是对于多个文件,它发送一个对象数组,但是对于单个文件,它只发送一个对象。