Javascript 即使在Node.js中使用回调函数之后,函数也会异步运行
我正在尝试使用Node.js的“fs”模块创建一个文件资源管理器 我编写了以下函数,它接收一个路径,并将该路径的内容(文件/文件夹)存储在一个数组中,然后使用回调函数将其发送回Javascript 即使在Node.js中使用回调函数之后,函数也会异步运行,javascript,node.js,callback,node-modules,fs,Javascript,Node.js,Callback,Node Modules,Fs,我正在尝试使用Node.js的“fs”模块创建一个文件资源管理器 我编写了以下函数,它接收一个路径,并将该路径的内容(文件/文件夹)存储在一个数组中,然后使用回调函数将其发送回 listDir: function (path, myCallback) { var resultObj = []; fs.readdir(path, function (err, data) { console.log('In listDir'); if (err) {
listDir: function (path, myCallback) {
var resultObj = [];
fs.readdir(path, function (err, data) {
console.log('In listDir');
if (err) {
return myCallback(err, null);
} else {
data.forEach(function (value) {
fs.lstat(path + '/' + value, function (err, stats) {
if (err) {
console.log(err);
} else {
//console.log('Size-' + stats.isFile()+'\n');
if(stats.isFile()){
//console.log('is file----\n');
/*resultObj.push({
type: 'file',
name: value,
size: stats['size']
});*/
resultObj.push(value);
console.log(resultObj+'\n');
} else if(stats.isDirectory()){
//console.log('is folder----\n');
/*resultObj.push({
type: 'folder',
name: value,
size: stats['size']
});*/
resultObj.push(value);
console.log(resultObj+'\n');
}
}
});
});
console.log('Resultant obj-' + resultObj);
return myCallback(null, resultObj);
}
});
}
对于“data”中存储的每个文件/文件夹,我将尝试检查它是文件还是文件夹,并根据需要将对象推入“resultObj”数组。
然而,return语句甚至在forEach完成之前就被执行,因此每次我都会得到一个空resultObj
为什么会这样?为什么即使我提供了回调函数,它也会异步运行
当我使用path参数调用/test路由时,输出是这样的--
在listDir中合成obj-
获取/测试?路径=F:\dummyFolder 304 15.210毫秒--
文件1
文件1、文件2
文件1、文件2、文件夹3
请帮我完成这项任务,我真的很忙,必须在今晚之前完成。作业中也特别提到了不使用“fs”模块的任何同步功能。 那么,我如何在牢记该条款的情况下做到这一点呢
PS:不要介意这些注释,我使用它们进行调试。问题在于您没有等待每个文件的
fs.lstat()
函数完成。您正在排队等待所有的fs.lstat()
调用,但并不等待它们全部完成。您只需返回resultObj
,此时它仍然是[]
您可以通过在data.forEach()
的回调中添加一个检查来解决此问题,以查看有多少项调用了fs.lstat()
的回调
listDir: (path, myCallback) => {
let resultObj = [];
fs.readdir(path, (err, data) => {
console.log('In listDir');
if (err) {
return myCallback(err);
}
let itemsCompleted = 0
data.forEach(value => {
fs.lstat(path + '/' + value, (err, stats) => {
itemsCompleted++
if (err) {
console.log(err);
} else {
if(stats.isFile() || stats.isDirectory()){
resultObj.push(value);
console.log(resultObj+'\n');
}
}
if(itemsCompleted >= data.length) {
return myCallback(null, resultObj)
}
});
});
}
然而,上述方法仍然比使用async/await
的承诺更复杂。使用async/await
承诺是当前处理节点中异步控制流的首选方法。利用promisifyfs.readdir()
和fs.lstat()
可以简化控制流程,并显著提高listDir()的可读性。此外,通过使用map()
const {promisify} = require('util')
const fs = require('fs')
const {join} = require('path')
const readdirAsync = promisify(fs.readdir)
const lstatAsync = promisify(fs.lstat)
module.exports = {
listDir: async path => {
let resultObj = [];
let entries = await readdirAsync(path)
console.log('In listDir');
await Promise.all(entries.map(async value => {
try {
let stats = await lstatAsync(join(path, value))
if(stats.isFile() || stats.isDirectory()){
resultObj.push(value);
console.log(resultObj+'\n');
}
} catch (err) {
console.log(err)
}
}))
return resultObj
}
}
谢谢!工作完美无瑕。