异步函数 - 这是'回调地狱'吗?

时间:2017-05-03 13:27:50

标签: javascript node.js asynchronous

我越来越多地了解节点,我遇到的最大问题是如何确定异步函数的工作原理。

fs.readdir(base, function (err, files) {
    if (!files.length) {
        console.log('No files');
    }
    for (var i in files) {
        fs.stat(files[i], function (err, stats) {
            if (stats.isDirectory()) {
                console.log(files[i]);
                console.log('FOLDER');
            } else {
                console.log(files[i]);
                console.log('FILE')
            }
        })
    }
});

base是一个包含两个子文件夹的文件夹,以及一个.DS_Store文件。命令行的输出为:

.DS_Store
FILE
/dir/to/file/index.js:115
      if (stats.isDirectory()) {
               ^

TypeError: Cannot read property 'isDirectory' of undefined

我现在的基本理解是存在这个问题,因为它全部是异步发生的 - 我最好的猜测是readdir回调不会'等待'fs.stat回调完成?我可能完全误解了它(实际上,从这个基础理解中学习的任何好文件都会有所帮助)。

我的下一个想法就像承诺一样?他们似乎解决了异步的许多问题,这将是我学习的下一个飞跃。

这是'回调地狱'吗?承诺是修复吗?有没有不同的方法来做到这一点?

1 个答案:

答案 0 :(得分:0)

这里可能存在一些问题,具体取决于您的其余代码。一个是fs.stat将路径作为第一个参数而不是文件名。如果您将函数调用更改为可能有用的fs.stat(base + '/' + files[i], function (err, stats)。但我不确定你的例子中base是什么。

其次,您应该在循环中使用ES6 let而不是var。异步函数将放在调用堆栈上,并在完成后按顺序处理。但是,到那时循环将一直运行,变量i将等于其在最后一次迭代中的值。另一方面,使用let定义的变量在范围上限于块,这意味着每个函数(因为它们位于不同的块中)将具有正确的i值。

尝试测试以下两个不同的版本,首先使用for (var i in files),然后使用for (let i in files),您将看到我的意思。

for (var i in files) {
        fs.stat(files[i], function (err, stats) {
            if (stats.isDirectory()) {
                console.log(files[i]);
                console.log('FOLDER');
                console.log(i);
            } else {
                console.log(files[i]);
                console.log('FILE')
                console.log(i);
            }
        })
    }

此外,正如您对问题的评论中所建议的,我建议您进行正确的错误处理。