Javascript 即使在Node.js中使用回调函数之后,函数也会异步运行

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) {

我正在尝试使用Node.js的“fs”模块创建一个文件资源管理器

我编写了以下函数,它接收一个路径,并将该路径的内容(文件/文件夹)存储在一个数组中,然后使用回调函数将其发送回

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
承诺是当前处理节点中异步控制流的首选方法。利用promisify
fs.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
  }
}

谢谢!工作完美无瑕。