Определить, когда рекурсивная функция завершена - PullRequest
4 голосов
/ 09 мая 2011

У меня есть функция, которая сначала выполняет поиск по большому графику.В настоящее время приложение работает и через некоторое время завершает работу.Я хочу добавить событие finished в EventEmitter.

Моей первой идеей было реализовать счетчик для каждого 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.

График очень нестабилен, и я делаю несколько вложенных асинхронных вызовов, которые могут потерпеть неудачу.Есть ли способ узнать, когда все асинхронные рекурсивные вызовы завершены без использования счетчика?

Ответы [ 4 ]

3 голосов
/ 10 мая 2011

Попробуйте что-то вроде этого:

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

По сути, вы просто увеличиваете счетчик перед каждым рекурсивным вызовом и уменьшаете его в конце вызова, чтобы эффективно подсчитывать количество незавершенных вызовов, когда он равен нулю, вы можете отправить свое событие.

2 голосов
/ 10 мая 2011

JavaScript является однопоточным.

Поэтому, если в Recursive(start); нет асинхронных вызовов, таких как setTimeout или ajax, можно безопасно инициировать завершенное событие после вызова рекурсивной функции.

Общие асинхронные API передают функцию done.

Значит, у вас будет

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

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

И пользователи должны звонить done, когда они закончат.

0 голосов
/ 17 октября 2017

Попробуйте что-нибудь подобное, основываясь на ответе 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" );
0 голосов
/ 09 мая 2011

Можете ли вы использовать логическое значение вне функции в качестве флага и изменять его значение при достижении целевого узла?Возможно, ваши рекурсивные случаи могут быть внутри логического случая, и когда узел найден, вы можете обновить его значение ... Или вы спрашиваете, каков базовый случай для завершения рекурсивной функции?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...