[英]NodeJS - Return a single status code from an async function using Array.protoype.map() to save multiple files in different locations in a database
I am a little stumped on how to handle this the best way possible.我对如何以最好的方式处理这个问题感到有些困惑。 I've decided to rewrite this controller, and I need to (at least I think) make use of
promise.all()
here.我决定重写这个控制器,我需要(至少我认为
promise.all()
在这里使用promise.all()
。
Premise:前提:
In this application, the Admin user must be able to bulk upload a bunch of .pdf's at once that are for multiple users.在此应用程序中,管理员用户必须能够一次批量上传一组供多个用户使用的 .pdf 文件。 The .pdf's adhere to a specific naming convention that my backend upload controller by using a
regEx
, pulls out a first and last name. .pdf 遵循特定的命名约定,我的后端上传控制器使用
regEx
提取名字和姓氏。 These .pdf's are auto-generated in a program, that always names them exactly the same, so there is no human error in misspelling names.这些 .pdf 是在程序中自动生成的,它们的名称始终完全相同,因此不会出现拼写错误的人为错误。
Each call to the database and an AWS S3 Bucket is made within an Array.prototype.map()
a function that is looping through and uploading a file to an S3 bucket, and then it takes the Key
name of the file returned from s3.upload()
and saves that Key
to a user model in Mongo DB as a reference to their file(s) within the S3 Bucket.对数据库和 AWS S3 存储桶的每次调用都在
Array.prototype.map()
函数中进行,该函数循环遍历并将文件上传到 S3 存储桶,然后获取从s3.upload()
返回的文件的Key
名称s3.upload()
并将该Key
保存到 Mongo DB 中的用户模型中,作为对其在 S3 存储桶中的文件的引用。
Example Code:示例代码:
This is what I currently have (that does work somewhat).这就是我目前所拥有的(确实有些作用)。 This is the block of code responsible for what I described above.
这是负责我上面描述的代码块。
employeeFiles
is created further up in the controller and contains an array of objects that each have a file
and id
property. employeeFiles
是在控制器中进一步创建的,它包含一个对象数组,每个对象都有一个file
和id
属性。 The file name destructuring and user matching happen further up in the controller as well, and the employeeFiles
array is a result of that.文件名解构和用户匹配也发生在控制器的更上方,
employeeFiles
数组是其结果。 The id
property contains the mongo _id
of the employee, and the file
property contains the file to be saved. id
属性包含员工的mongo _id
, file
属性包含要保存的文件。 This all works perfectly, and I don't think that code is needed for context here.这一切都很完美,我认为这里的上下文不需要代码。
fileType
is a variable available within the scope of the controller: fileType
是控制器范围内可用的变量:
const employeeFileUploadToDb = () => {
employeeFiles.map((employee, i) => {
const { file, id } = employee;
const params = {
Bucket: S3_BUCKET_NAME,
Body: file.buffer,
Key: `${filetype}/${file.originalname}`
};
s3.upload(params, (err, data) => {
if (err) {
next(err);
}
if (data) {
//Save reference to Employee model
let dataObj = {
key: data.key,
fileName: file.originalname,
date: Date.now()
};
Employee.findOneAndUpdate(
{ _id: id },
{ $push: { [`${filetype}`]: dataObj } }
)
.then(resp => res.send(200))
.catch(err => next(err));
}
});
});
};
I am making use of next()
to handle any errors within the s3.upload()
and findOneAndUpdate()
functions (I do realize findOneAndUpdate()
is deprecated) moving forward.我正在使用
next()
来处理s3.upload()
和findOneAndUpdate()
函数中的任何错误(我确实意识到findOneAndUpdate()
已被弃用)向前推进。 My idea here is that if there is an error with one of the functions, next()
will send it to my error handler middleware and keep going, versus ending the process and halting all of it.我的想法是,如果其中一个函数出现错误,
next()
会将其发送到我的错误处理程序中间件并继续运行,而不是结束进程并停止所有进程。
Inside of every iteration of s3.upload()
, I make a call to my database so that I can save the reference to the file uploaded to the S3 Bucket
.在
s3.upload()
的每次迭代中,我都会调用我的数据库,以便我可以保存对上传到S3 Bucket
的文件的引用。 Inside of a then()
method of Employee.findOneAndUpdate()
, I return a (200)
response to let my client know everything has been uploaded to S3 and saved in my DB.在
Employee.findOneAndUpdate()
的then()
方法中,我返回一个(200)
响应,让我的客户知道所有内容都已上传到 S3 并保存在我的数据库中。 So on each iteration of this map()
function, I am returning a 200. If I have 10 files, I am returning 200 10 times.所以在这个
map()
函数的每次迭代中,我返回 200。如果我有 10 个文件,我将返回 200 10 次。
I feel that I can convert this into an async
function, and make use of a promise.all()
to return a single status code upon completion.我觉得我可以将其转换为
async
函数,并在完成时使用promise.all()
返回单个状态代码。 Returning that many status codes seem a bit crazy to me.返回这么多状态代码对我来说似乎有点疯狂。 But I am not too sure how to approach this while using a
map()
function to loop and make an async call on every iteration.但是我不太确定如何在使用
map()
函数循环并在每次迭代时进行异步调用时解决这个问题。
Hope this makes sense, and thank you in advance for looking at this!希望这是有道理的,并提前感谢您查看此内容!
I would split it up into a 2-step process.我会把它分成一个两步的过程。 Upload in bulk and then save to mongo if it all worked out.
批量上传,如果一切顺利,然后保存到 mongo。
const employeeFileUploadToDb = () => {
const uploadFiles = files => files.map((employee, i) => new Promise((resolve, reject) => {
//...
s3.upload(params, (err, data) => {
if (err) {
return reject(err);
}
resolve(data);
})
});
});
Promise.all(uploadData(employeeFiles)).then((err, data) => {
// Handle saving to mongo
})
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.