Javascript 确定递归函数何时完成

Javascript 确定递归函数何时完成,javascript,reflection,recursion,node.js,Javascript,Reflection,Recursion,Node.js,我有一个函数,在一个大图上进行广度优先搜索。 目前该应用程序正在运行,并在一段时间后完成。 我想向EventEmitter添加一个finished事件 我的第一个想法是为每个递归进程实现一个计数器。 但是,如果某个递归进程不调用计数器--方法,则此操作可能会失败 var App = function(start, cb) { var Recursive = function(a, cb) { // **asynchronous** and recursive breadth

我有一个函数,在一个大图上进行广度优先搜索。 目前该应用程序正在运行,并在一段时间后完成。 我想向EventEmitter添加一个
finished
事件

我的第一个想法是为每个
递归
进程实现一个计数器。 但是,如果某个
递归
进程不调用
计数器--
方法,则此操作可能会失败

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
消息

编辑应用程序没有在图中搜索内容,它必须遍历整个图才能完成。现在还不知道图中有多少元素

Edit2类似计算反射的东西是完美的,但它似乎不存在于javascript中

图形非常不稳定,我正在执行一些嵌套异步调用,这些调用都可能失败。
有没有一种方法可以知道在不使用计数器的情况下所有异步递归调用何时完成?

是否可以使用函数外部的布尔值作为标志,并在到达目标节点时更改其值?也许您的递归事例可以在布尔型上的事例中,当找到节点时,您可以更新它的值。。。或者您正在询问递归函数要完成的基本情况是什么?

请尝试以下操作:

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); 
};

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

JavaScript是单线程的

所以除非<代码>递归(开始)中有异步调用,如
setTimeout
ajax
调用递归函数后触发已完成事件是安全的

通用异步API传递一个
done
函数

所以你会

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

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

完成后,用户可以调用
done

根据阿德里安的回答尝试类似的方法

/**
 * 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" );
/**
*函数从基本目录递归搜索文件
*返回与搜索匹配的文件的绝对路径数组
*标准
*/
让recursiveFileSearch=(baseDir,fileId)=>{
设pathsArray=[];
pendingRecursive=1;
//获取所有配置路径的递归函数
让GetFilePath=(baseDir)=>{
//需要内置路径和文件系统模块
let path=require('path');
设fs=require('fs');
//读取基本目录中的文件
让files=fs.readdirSync(baseDir);
//递归获取所有配置文件
for(设i=0;i
@Atticus:奇怪,我不这么看。这个问题真的不清楚!!为什么不能在函数的最后一行发出递归(开始)?调用递归(开始)后,应用程序在技术上完成。但递归函数仍在计算中。我想在所有递归函数完成后发出finished,我可能严重误解了一些东西,但在我看来,在
Recursive(start)之后在行上触发事件
表示只有在函数返回后,即在所有递归完成后,才会执行它。我错过了什么?这里没有多线程…如果您需要帮助,我建议您在这里发布
递归
函数代码,或者如果它在这里太大:它更像是对完整图形的遍历,而不是搜索。我问的是如何知道应用程序中的所有递归调用是否正确完成——宽度优先的子->兄弟姐妹->子->兄弟姐妹,重复,对吗?所以我会对节点总数使用递减计数器,每次访问递减。一旦0,完成,否则将升起找到节点的标志。。如果考虑到它是异步的,
递归
函数被调用了两次,而这两次调用在第三次调用之前就完成了,会发生什么?我得说这不管用。你假设,这些电话首先是一起打的,我认为这在大多数情况下都有效。但是在我的例子中,对于一个大目录中的文件和子目录,在列出文件和目录之后在每个子目录中调用递归调用,我猜这种方法不起作用,因为计数器可能会在列表完成之前达到
0
,因为您假设它像堆栈一样工作。