开发者

Node.js: When do you know when a collection of asynchronous tasks is done?

开发者 https://www.devze.com 2023-03-25 18:10 出处:网络
I would like to descend a directory, and examine the name of every file I see there against a regular expression.Basically, a version of the common unix find command, only written in Node.js.I don\'t

I would like to descend a directory, and examine the name of every file I see there against a regular expression. Basically, a version of the common unix find command, only written in Node.js. I don't care about the order of the files, but I do want to make sure I get all of them.

I have the following code, which is close (I think) to what I want. It takes a startdir, a regexp, and a callback; for each file it analyzes it increments the value of sentinel by one, and when it is done with the analysis it decrements the sentinel. My concern is that if there's one file, and a deeply nested collection of directories, it will analyze that file and trigger the callback long before it finds a second file, and possible the callback will be called twice.

Obviously, I could prevent the callback from being called twice by having a fired variable to restrain it from firing a second time. But that still would give me erroneous data. What am I doing wrong here, and is there a more node-appropriate way to do it?

fs = require('fs')
path = require('path')

function get_all_files(startdir, regexp, callback) {
    var sentinel = 0;
    var results = [];

    function check_sentinel() {
        sentinel--;
        if (sentinel === 0) {
            callback(results);
        }
    }

    function check_file(dir, filename) {
        var fname;
        sentinel++;
        if (regexp.test(filename)) {
            results.push(path.join(dir, filename));
        }
        check_sentinel();
    }

    function check_directory(dir) {
        fs.readdir(path.join(this.rootpath, dirpath), function(err, files) {
            var fname, i, len, npath;
            if (err) {
                throw err
            }

            for (i = 0, len = files.length; i < len; i++) {
                fname = files[i];
                npath = path.join(dir, fname);
                fs.stat(npath, function(err, stats) {
                    if (stats.isFile()) {
                        check_file(dir, fname);
     开发者_JAVA百科               } else {
                        if (stats.isDirectory()) {
                            check_directory(npath);
                        }
                    }
                });
            }
        });
    }
    check_directory(startdir);
}


A couple of thoughts...

I have never used it, but the simplest way to do what you are asking might be to use the async.js walkfiles function. See the tests for an example here.

Otherwise, I would consider building an array of function calls and returning the array from your recursive directory walking function (rather than using a sentinel, etc). In other words, check_directory returns an array of function calls matching the files you are looking for. If there is no file, the array is empty.

Finally, combine the array at the top of the recursion and use the async library (not the same as async.js) to execute the array of functions all at once using the parallel function (see this thread for an example using "series").

0

精彩评论

暂无评论...
验证码 换一张
取 消