Determine when recursive function is finished
I have a function that does a breadth first search over a big graph.
Currently the App runs and is finished after some time.
I want to add a finished
Event to the EventEmitter.
My first idea was to implement a counter for each Recursive
process.
But this could fail if some Recursive
process does not call the counter--
method.
var App = function(start, cb) {
var Recursive = function(a, cb) {
// **asynchronous** and recursive breadth-first search
}
var eventEmitter = new EventEmitter();
cb(eventEmitter);
Recursive(start);
};
How can I emit the finished
message if all Recursive
functions are finished.
Edit App is not searching something in the graph, it has to traversal the complete graph in order to finish. And it is not known how many elements are in the graph.
Edit2 Somet开发者_运维知识库hing like computational reflection would be perfect, but it does not seem to exist in javascript.
The Graph is very unstable and I am doing a few nested asynchronous calls which all could fail. Is there a way to know when all asynchronous recursive calls are finished without using a counter?
JavaScript is single threaded.
So unless Recursive(start);
has asynchronous calls in it like setTimeout
or ajax
it's safe to just trigger your finished event after calling the recursive function.
General asynchronous APIs pass around a done
function.
So you would have
Recursive(start, function() {
// trigger finished.
});
var Recursive = function(a, done) {
...
};
And it's upto users to call done
when they are done.
Try something like this :
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);
};
Basically, you just increment a counter before each recursive call, and decrement it at the end of the call, so you're effectively counting the number of unfinished calls, when it's zero, you can then emit your event.
Try something like this based on Adriens answer
/**
* 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" );
Can you use a boolean outside of the function as a flag and change it's value upon reaching your targetted node? Perhaps your recursive cases can be within a case on the boolean, and when the node is found you can update it's value... Or are you asking what the base case is for your recursive function to complete?
精彩评论