我有一个功能,可以在大图上进行广度优先搜索。
目前,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非常不稳定,我正在做一些嵌套的异步调用,这些调用都可能失败。 有没有办法知道何时完成所有异步递归调用而不使用计数器?
答案 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);
中有setTimeout
或ajax
之类的异步调用,否则在调用递归函数后触发已完成的事件是安全的。
通用异步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" );