我在Node.js中有一个复杂的递归函数,为了这个问题,我将其简化为以下内容:
function sum(tree) {
if (!tree) return 0;
var sumLeft = sum(tree.left);
var sumRight = sum(tree.right);
return sumLeft + tree.val + sumRight;
}
var exampleTree = {
val: 3,
right: { val: 4 },
left: { val: 5,
right: {val: 6},
left: {val: 7}
}
}
console.log(sum(exampleTree)); // returns 25 = 3+4+5+6+7
现在我要转换功能" sum"到异步函数:
function sumAsync(tree, callback) {
// ???
}
但是,由于函数现在没有返回值,我不知道如何获取值sumRight和sumLeft并将它们组合起来。
一种可能的选择是完全重写算法,使其迭代而不是递归(如本问题所示:how to make this synchronous recursive function asynchronous)。但是,在许多情况下,这可能非常复杂,并使整个程序不可读。有没有一种解决方案可以保持递归函数的简单结构,同时使其异步?
注意:我的问题不是对树中的值求和... ...树和函数只是一个最小工作示例。
编辑:根据vkurchatkin的回答和评论,我决定使用async.parallel。这是结果:
var async = require("async");
function sumAsync (tree, callback) {
if (!tree) return setImmediate(callback.bind(null, null, 0));
async.parallel([
sumAsync.bind(this, tree.left),
sumAsync.bind(this, tree.right),
],
function(err, results) {
callback(err, tree.val+results[0]+results[1]);
});
}
sumAsync(exampleTree, function(err, result) {
console.log(result); // prints 25
});
答案 0 :(得分:1)
这样的事可能有用:
function sumAsync (tree, callback) {
if (!tree) return setImmediate(callback.bind(null, null, 0));
var pending = 3;
var sum = 0;
var done = false;
function handleError (err) {
if (!done) {
callback(err);
done = true;
}
}
function _callback (err, res) {
if (err) return handleError(err);
sum += res;
if (!--pending && !done) {
done = true;
callback(null, sum);
}
}
tree.fetchLeft(function (err, left) {
if (err) return handleError(err);
sumAsync(left, _callback);
});
tree.fetchRight(function (err, right) {
if (err) return handleError(err);
sumAsync(right, _callback);
});
tree.fetchValue(_callback);
}
它可能看起来很复杂,但它实际上只是一个临时的async.parallel
实现,所以你可以改用它。
答案 1 :(得分:0)
假设树结构从一开始就存在,而不是一块一块地取出(我认为这是一种非常糟糕的做法)。
var exampleTree = {
val: 3,
right: { val: 4 },
left: { val: 5,
right: {val: 6},
left: {val: 7}
}
}
function sum(tree,callback){
if(!tree){
if(callback!==undefined){ return callback(0); }
return 0;
}
var sumLeft=sum(tree.left);
var sumRight=sum(tree.right);
var v = sumLeft+tree.val+sumRight;
// callback is **not** passed so we continue
if(callback===undefined){
return v;
}else{ // callback is passed meaning this is the root, end this.
return callback(v);
}
};
sum(null,function(result){
console.log(result); // logs 0
});
sum(exampleTree,function(result){
console.log(result); // logs 25
});
console.log(sum(exampleTree)); // logs 25