我搜索并阅读了有关异步函数和回调的信息。但是我有一个星期无法解决我的问题。我想按顺序在循环内执行“ fs readfile”。我尝试以下方法,但不成功。
// on the code below, console.log print the value in random order and 'storedata' is empity.
// my goal is to do readfile in loop orderly and store the value
router.get("/files/readfiles", function(req,res){
var storedata= [];
var filenames= ["file1","file2","file3","file4"];
for (var i=0; i< filenames.length; i++){
fs.readFile('views/allfiles/'+ filenames[i] +'.ejs','utf8',function (err, data) {
if (err) throw err;
storedata.push(data);
console.log(data);
});
console.log(storedata); // this returns empty array
});
我也尝试另一种方式:
router.get("/files/readfiles", function(req,res){
var filenames= ["file1","file2","file3","file4"];
filenames.forEach(readfiles);
function readfiles(value) {
var dataread = fs.readFile('views/allfiles/'+ value +'.ejs','utf8')
console.log (dataread);
}
});
在上面的尝试中,我收到以下错误:TypeError [ERR_INVALID_CALLBACK]:回调必须是一个函数。
我对异步方法是陌生的,请提供任何帮助。
答案 0 :(得分:0)
如果您使用的是Node v10或更高版本,则可以使用fs promises API和async / await。
要连续阅读文件:
router.get( "/files/readfiles", async function( req, res ) {
const storedata = [ ];
const filenames = [ "file1", "file2" , "file3", "file4" ];
for (let i = 0; i < filenames.length; i++ ) {
const data = await fs.promises.readFile( 'views/allfiles/'+ filenames[i] +'.ejs', { encoding: 'utf8' } );
storedata.push( data );
}
console.log( storedata );
} );
或并行阅读它们:
router.get( "/files/readfiles", async function( req, res ) {
const promises = [ ];
const filenames = [ "file1", "file2", "file3", "file4" ];
for (let i = 0; i < filenames.length; i++ ) {
const promise = fs.promises.readFile( 'views/allfiles/'+ filenames[i] +'.ejs', { encoding: 'utf8' } );
promises.push( promise );
}
const storedata = await Promise.all( promises );
console.log( storedata );
} );
答案 1 :(得分:0)
您应该像这样使用ES2017 async/await
语法。
router.get("/files/readfiles", async function(req, res){
var storedata= [];
var filenames= ["file1","file2","file3","file4"];
for (var i=0; i< filenames.length; i++){
await new Promise((resolve, reject) => {
fs.readFile('views/allfiles/'+ filenames[i] +'.ejs','utf8',function (err, data) {
if (err) return reject( err )
storedata.push(data);
resolve();
});
})
console.log(storedata);
}
});
答案 2 :(得分:-1)
您的第二个代码不提供回调函数,这就是您的错误。
您的第一个代码,您正在尝试使用回调,因此您需要遵循嵌套在回调中的代码,这就是所谓的回调地狱
它看起来像这样:
router.get("/files/readfiles", function(req,res){
var storedata= [];
var filenames= ["file1","file2","file3","file4"];
for (let i = 0; i< filenames.length; i++){
fs.readFile('views/allfiles/'+ filenames[i] +'.ejs','utf8',function (err, data) {
if (err) throw err;
storedata[i] = data;
if (storedata.length === filenames.length) {
console.log(storedata);
// do stuff you want, like:
res.send(storedata)
}
});
});
如果计划使用节点10,建议您使用Promise.all查看其他答案。异步/等待很棒