确定递归函数何时完成

时间:2011-05-09 08:05:12

标签: javascript reflection recursion node.js

我有一个功能,可以在大图上进行广度优先搜索。 目前,App运行并在一段时间后完成。 我想在EventEmitter中添加finished事件。

我的第一个想法是为每个Recursive进程实现一个计数器。 但是,如果某些Recursive进程未调用counter--方法,则可能会失败。

var App = function(start, cb) {
    var Recursive = function(a, cb) {
       // **asynchronous** and recursive breadth-first search
    }

    var eventEmitter = new EventEmitter();
    cb(eventEmitter);
    Recursive(start); 
};

如果所有finished函数都已完成,我如何发出Recursive消息。

编辑应用不会搜索图表中的内容,必须遍历完整的图表才能完成。并且不知道图中有多少元素。

Edit2 像计算反射这样的东西会很完美,但它似乎不存在于javascript中。

Graph非常不稳定,我正在做一些嵌套的异步调用,这些调用都可能失败。 有没有办法知道何时完成所有异步递归调用而不使用计数器?

4 个答案:

答案 0 :(得分:3)

尝试这样的事情:

var App = function(start, cb) {
  var pendingRecursive = 0;
  var eventEmitter = new EventEmitter();
  cb(eventEmitter);

  var Recursive = function(a) {
    // breadth-first search recursion

    // before each recursive call:
    pendingRecursive++;
    Recursive(/*whatever*/);

    // at the end of the function
    if (--pendingRecursive == 0){
      eventEmitter.emit('end');
    }
  }

  pendingRecursive = 1;
  Recursive(start); 
};

基本上,你只是在每次递归调用之前递增一个计数器,并在调用结束时递减计数器,这样你就可以有效地计算未完成的调用次数,当它为零时,你可以发出你的事件。

答案 1 :(得分:2)

JavaScript是单线程的。

因此,除非Recursive(start);中有setTimeoutajax之类的异步调用,否则在调用递归函数后触发已完成的事件是安全的。

通用异步API传递done函数。

所以你会有

Recursive(start, function() {
    // trigger finished.
});

var Recursive = function(a, done) {
    ...
};

完成后,用户可以调用done

答案 2 :(得分:0)

你可以在函数外部使用布尔值作为标志,并在到达目标节点时更改它的值吗?也许你的递归情况可以在布尔值的情况下,并且当找到节点时你可以更新它的值......或者你在问你的递归函数完成的基本情况是什么?

答案 3 :(得分:0)

根据Adriens的回答尝试这样的事情

/**
 * Function to search for a file recursively from a base directory
 * returns an array of absolute paths for files that match the search
 * criteria
 */


let  recursiveFileSearch  = ( baseDir, fileId ) => {


    let pathsArray = [];
    pendingRecursive = 1;


    //recursive funcion to get all config paths
    let getFilePaths = ( baseDir ) => {

        //require inbuilt path and filesystem modules
        let path = require ( 'path' );
        let fs   = require ( 'fs' );

        //read the files in the base directory
        let files = fs.readdirSync ( baseDir );

        //fetch all config files recursively
        for ( let i = 0 ; i < files.length; i ++ ) {

            let file     = files [ i ];
            let filePath = path.resolve ( baseDir, file );

            //get file stats
            let fileStats = fs.lstatSync ( filePath );
            let isFile    = fileStats.isFile ( );
            let isDir     = fileStats.isDirectory ( );

            if  ( isFile && file === fileId ) {
                pathsArray.push ( filePath );
            }

            if  ( isDir ) {

                pendingRecursive++;
                getFilePaths( filePath );
            }

        }

        //decrement the recursive flag
        if (--pendingRecursive == 0){
            return pathsArray;
        }  



    };

    return  getFilePaths ( baseDir );

};


//Testing the recursive search
let baseDir = __dirname;
let filePaths = recursiveFileSearch  ( baseDir, "your file name" );