节点 js 异步和等待功能 - 强制功能完成?
node js async & await functions - force the function to complete?
我正在尝试使用 angular 表单中的组件 (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!" };
}
您不应该在 async
函数中直接调用接受回调的函数。这就是为什么您的 try-catch 捕获任何错误的机会较小。相反,return 一个 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
函数应该调用另一个 return 是 Promise
的函数,这样 await
关键字有助于简化代码并处理抛出的错误.要使用这种用法,请编写一个新函数来使 form.parse
异步,并替换 fs
支持 returning 为 Promise
的东西,例如 fs.Promise
API or 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 use
var
keyword声明一个局部变量。请改用 const
或 let
。
- 避免在 for 循环中使用
await
关键字,除非您打算一个一个地迭代元素。
最简单的方法是制作一个辅助函数,使 nodestyle fn 成为 return 一个承诺,然后使用它
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!" };
}
我正在尝试使用 angular 表单中的组件 (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!" };
}
您不应该在 async
函数中直接调用接受回调的函数。这就是为什么您的 try-catch 捕获任何错误的机会较小。相反,return 一个 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
函数应该调用另一个 return 是 Promise
的函数,这样 await
关键字有助于简化代码并处理抛出的错误.要使用这种用法,请编写一个新函数来使 form.parse
异步,并替换 fs
支持 returning 为 Promise
的东西,例如 fs.Promise
API or 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 use
var
keyword声明一个局部变量。请改用const
或let
。 - 避免在 for 循环中使用
await
关键字,除非您打算一个一个地迭代元素。
最简单的方法是制作一个辅助函数,使 nodestyle fn 成为 return 一个承诺,然后使用它
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!" };
}