node js async & await 函数 - 强制函数完成?
Posted
技术标签:
【中文标题】node js async & await 函数 - 强制函数完成?【英文标题】:node js async & await functions - force the function to complete? 【发布时间】:2021-05-22 07:17:26 【问题描述】:我正在尝试使用组件(summernote)以角度形式上传图像。
我配置了uploadImagePath
端点以将图像提交到我的nodejs 后端,但在我的代码中,outputFileName
字段返回为空。
如何确保功能完成?
async uploadFile(req)
var multiparty = require('multiparty');
var form = new multiparty.Form();
let outputFileName = '';
try
form.parse(req, function(err, fields, files)
var imgArray = files.image;
for (var i = 0; i < imgArray.length; i++)
var singleImg = imgArray[i];
outputFileName = singleImg.originalFilename;
fs.readFile(singleImg.path , function(err,data)
fs.writeFile('./public/images/'+outputFileName,data, function(err)
if (err) console.log('ERRRRRR!! :'+err);
console.log('Fitxer: ' + outputFileName);
)
)
);
catch (ex)
throw ex;
return error: false, outputFileName: outputFileName, msg: "File uploaded!" ;
【问题讨论】:
请更新您的问题标题以更详细地反映问题 为什么将uploadFile
设置为async
函数?
不管你有没有,都是一样的。这里的问题是返回发生在 form.parse 完成之前
【参考方案1】:
您不应直接调用在async
函数中接受回调的函数。这就是为什么您的 try-catch 捕获任何错误的机会较小的原因。相反,请返回 Promise
来处理该错误。
function uploadFile(req)
return new Promise((resolve, reject) =>
const multiparty = require('multiparty')
const form = new multiparty.Form()
let outputFileName = ''
form.parse(req, function (err, fields, files)
if (err)
reject(err)
return
const imgArray = files.image
// You should not call function that accepts a callback in for loop
// Lets assumed imageArray has only one element.
// for (let i = 0; i < imgArray.length; i++)
const singleImg = imgArray[0 /* i */]
outputFileName = singleImg.originalFilename
fs.readFile(singleImg.path, function (err, data)
if (err)
reject(err)
return
fs.writeFile('./public/images/' + outputFileName, data, function (err)
if (err)
reject(err)
return
console.log('Fitxer: ' + outputFileName)
resolve(
error: false,
outputFileName: outputFileName,
msg: "File uploaded!"
)
)
)
//
);
)
但如您所见,上面的代码很乱,for 循环不起作用。为了解决这个问题,我们应该让uploadFile
异步,这里不能使用回调。
async
函数应尽可能调用另一个返回 Promise
的函数,以便 await
关键字有助于简化代码并处理抛出的错误。要实现这样的用法,请编写一个新函数来使 form.parse
异步,并将 fs
替换为支持返回 Promise
的东西,例如 fs.Promise
API 或 fs-extra
package。
const fs = require('fs-extra')
const multiparty = require('multiparty')
function parseForm(req)
return new Promise((resolve, reject) =>
const form = new multiparty.Form()
form.parse(req, function (err, fields, files)
if (err) reject(err)
else resolve(files)
)
)
async function uploadFile(req)
let outputFileName = ''
const files = await parseForm(req)
const imgArray = files.image
// Now we can use for loop
for (let i = 0; i < imgArray.length; i++)
const singleImg = imgArray[i]
outputFileName = singleImg.originalFilename
const data = await fs.readFile(singleImg.path)
await fs.writeFile('./public/images/' + outputFileName, data)
console.log('Fitxer: ' + outputFileName)
return
error: false,
outputFileName: outputFileName,
msg: "File uploaded!"
不过,您的代码仍然存在一些问题。 outputFileName
被多次分配,这使您的目的难以理解。出于这个原因,我无法重写您的代码,使其符合您的预期。
顺便说一句,应该考虑更多条件。这个我就不多说了。
建议not usevar
keyword 声明一个局部变量。请改用const
或let
。
避免在 for 循环中使用 await
关键字,除非您打算逐个迭代元素。
【讨论】:
【参考方案2】:最简单的方法是创建一个辅助函数,让 nodestyle fn 返回一个 promise,然后使用它
function parseMultiparty(req)
return new Promise((resolve, reject) =>
var form = new multiparty.Form();
form.parse(req, function(err, fields, files)
if(err) reject(err) else resolve([fields, files])
)
)
async uploadFile(req)
var multiparty = require('multiparty');
var form = new multiparty.Form();
let outputFileName = '';
try
const [fields, files] = await parseMultiparty(req)
var imgArray = files.image;
for (var i = 0; i < imgArray.length; i++)
var singleImg = imgArray[i];
outputFileName = singleImg.originalFilename;
const data = await fs.promises.readFile(singleImg.path)
console.log('Fitxer: ' + outputFileName);
try
await fs.promises.writeFile('./public/images/'+outputFileName,data)
catch(err) console.log('ERRRRRR!! :'+err);
catch (ex)
throw ex;
return error: false, outputFileName: outputFileName, msg: "File uploaded!" ;
【讨论】:
以上是关于node js async & await 函数 - 强制函数完成?的主要内容,如果未能解决你的问题,请参考以下文章
Node.js 7 的 async await 终于来了,不过怎么觉得没啥用
Node.js - 使用 'async' 和 'await' 和 sequelize ORM
Node.js 最佳实践异常处理——在 Async/Await 之后