从asynchronousrecursion函数中返回一个值

我在Node.js中有一个复杂的recursion函数,为了这个问题,我简化了以下内容:

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”转换成一个asynchronous函数:

 function sumAsync(tree, callback) { // ??? } 

但是,因为函数现在不返回一个值,我不知道如何获得值sumRight和sumLeft并将它们合并。

一种可能的select是完全重写algorithm,使得它是迭代的而不是recursion的(正如在这个问题中所build议的: 如何使这个同步recursion函数asynchronous )。 但是,在很多情况下,这可能会非常复杂,使整个程序无法读取。 有没有一种解决scheme保持recursion函数的简单结构,同时使其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 }); 

像这样的东西可能会工作:

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

它可能看起来很复杂,但它实际上只是一个ad hoc的async.parallel实现,所以你可以直接使用它。

假设树结构从一开始就不存在,而且不是一片一片的(我认为这是一个非常糟糕的做法)。

 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