如何指示“;熟度;在异步操作中

How to indicate "doneness" in an async operation

本文关键字:熟度 异步操作 何指示 指示      更新时间:2023-09-26

给定这段计算给定目录和子目录中文件的代码,我该如何指示操作完成?

function walkDirs(dirPath) {
    var fs = require('fs'),
        path = require('path'),
        events = require('events'),
        count = 0,
        emitter = new events.EventEmitter();
    function walkDir(dirPath) {
        function readDirCallback(err, entries) {
            for (var idx in entries) {
                var fullPath = path.join(dirPath, entries[idx]);
                (function statHandler(fullPath) {
                    fs.stat(fullPath, function statEach(err, stats) {
                        if (stats) {
                            if (stats.isDirectory()) {
                                walkDir(fullPath);
                            } else if (stats.isFile()) {
                                count += 1;
                                emitter.emit('counted', count, fullPath);
                            }
                        }
                    });
                })(fullPath);
            }
        }
        fs.readdir(dirPath, readDirCallback);
    }
    walkDir(dirPath);
    return emitter;
}
var walker = walkDirs('C:');

我已经试过了,

  • 在我认为合适的地方,特别是在fs.readdir(dirPath, readDirCallback)呼叫之后,触发一个事件来表示"完成"
  • 修改CCD_ 2以返回添加的计数。(我意识到这实际上与在该函数中增加count没有什么不同

这两个都失败了,因为选中时,count的值为0。我已经确定我不会等到操作(清点文件)完成。显然,我需要在完成时触发回调或事件以获得正确的计数。

我知道代码正在成功计数,因为在附加调试器时,计数值是预期的。

在这一点上,我已经相当肯定地决定,我不知道如何进一步进行。特殊-

如何在异步操作中实现指示"完成"

异步Javascript函数通常在完成时调用回调函数。在这种情况下,如果您有其他事件,则done事件是合适的。承诺现在通常比回调更受欢迎,但你确实需要首先了解回调。

由于readdir是异步的,在下一行执行并不意味着它已经完成。这就是异步代码与同步代码相比令人困惑的地方。如果我是你,我会使用调试器并逐步完成一些非常简单(比这个更简单)的异步示例。这确实需要一段时间才能适应,而且很棘手。

有关漫游目录,请参见https://www.npmjs.com/package/walk。你不想在这里重新发明轮子。请务必使用谷歌和/或在npmjs上搜索现有模块。

一旦你确定你真正理解了回调和异步代码,那么你就可以转到async模块,然后用bluebird、ES6 promise等进行promisehttps://www.npmjs.com/package/co可能是有用的。

您可以通过使用promise来实现这一点。在这个例子中,我选择了Q.

npm install q

只要您认为异步函数是通过调用.resolve()函数来完成的,就可以解决您的承诺。当您的promise得到解决时,它将在promise对象的.then()函数中调用您的成功回调,即walkDirs。每当您的承诺得到解决或拒绝时,.then()函数就会被触发。如果您拒绝,您承诺将调用错误回调。

var q = require('q');
function walkDirs(dirPath) {
    var deffered = q.defer();
    var fs = require('fs'),
        path = require('path'),
        events = require('events'),
        count = 0,
        emitter = new events.EventEmitter();
    function walkDir(dirPath) {
        function readDirCallback(err, entries) {
            for (var idx in entries) {
                var fullPath = path.join(dirPath, entries[idx]);
                (function statHandler(fullPath) {
                    fs.stat(fullPath, function statEach(err, stats) {
                        if (stats) {
                            if (stats.isDirectory()) {
                                walkDir(fullPath);
                            } else if (stats.isFile()) {
                                count += 1;
                                emitter.emit('counted', count, fullPath);
                                deffered.resolve(emitter); // resolve promise
                            }
                        }
                    });
                })(fullPath);
            }
        }
        fs.readdir(dirPath, readDirCallback);
    }
    walkDir(dirPath);
    return q.promise;
}
walkDirs('C:')
   .then(success, error) //can also take error callback if promise is rejected.

function success(function(data) {
  //data = resolved data.
  console.log("is successfully done");
})
function errer(function() {
  console.log("is errorly done");
})