我希望在递归函数完全完成时执行回调,该函数可以持续不确定的时间量。我正在为异步问题而苦苦挣扎,希望能在这里得到一些帮助。使用request
模块的代码如下:
var start = function(callback) {
request.get({
url: 'aaa.com'
}, function (error, response, body) {
var startingPlace = JSON.parse(body).id;
recurse(startingPlace, callback);
});
};
var recurse = function(startingPlace, callback) {
request.get({
url: 'bbb'
}, function(error, response, body) {
// store body somewhere outside these funtions
// make second request
request.get({
url: 'ccc'
}, function(error, response, body) {
var anArray = JSON.parse(body).stuff;
if (anArray) {
anArray.forEach(function(thing) {
request.get({
url: 'ddd'
}, function(error, response, body) {
var nextPlace = JSON.parse(body).place;
recurse(nextPlace);
});
})
}
});
});
callback();
};
start(function() {
// calls final function to print out results from storage that gets updated each recursive call
finalFunction();
});
似乎一旦我的代码在嵌套请求中经过 for
循环,它就会继续执行请求并结束初始函数调用,而递归调用仍在继续。我希望它在所有嵌套递归调用完成之前不完成最高级别的迭代(我无法知道有多少)。
非常感谢任何帮助!
最佳答案
在您的示例中,您没有递归调用。如果我理解正确的话,你想说 recurse(point, otherFunc);
是递归调用的开始。
然后回到递归调用的定义(你没有在你的帖子中显示)并执行此操作(为要在递归结束时调用的回调函数添加第三个参数;调用者将传递它作为参数):
function recurse(startingPlace, otherFunc, callback_one) {
// code you may have ...
if (your_terminating_criterion === true) {
return callback_one(val); // where val is potentially some value you want to return (or a json object with results)
}
// more code you may have
}
然后在您发布的原始代码中,进行此调用(在最里面的部分):
recurse(startingPlace, otherFunc, function (results) {
// results is now a variable with the data returned at the end of recursion
console.log ("Recursion finished with results " + results);
callback(); // the callback that you wanted to call right from the beginning
});
只需花一些时间并尝试理解我的解释。当你理解了,你就会知道 Node 。这是一篇文章中的 Node 哲学。我希望它是清楚的。您的第一个示例应如下所示:
var start = function(callback) {
request.get({
url: 'aaa.com'
}, function (error, response, body) {
var startingPlace = JSON.parse(body).id;
recurse(startingPlace, otherFunc, function (results) {
console.log ("Recursion finished with results " + results);
callback();
});
});
};
以下只是您感兴趣时的附加信息。否则,您将接受上述设置。
通常在 node.js 中,人们也会返回一个错误值,以便调用者知道被调用的函数是否已成功完成。这里没有什么大的奥秘。人们不是只返回结果
,而是调用表单
return callback_one(null, val);
然后在另一个函数中你可以有:
recurse(startingPlace, otherFunc, function (recError, results) {
if (recErr) {
// treat the error from recursion
return callback(); // important: use return, otherwise you will keep on executing whatever is there after the if part when the callback ends ;)
}
// No problems/errors
console.log ("Recursion finished with results " + results);
callback(); // writing down `return callback();` is not a bad habit when you want to stop execution there and actually call the callback()
});
根据我的建议更新
这是我对递归函数的建议,但在此之前,您似乎需要定义自己的get
:
function myGet (a, callback) {
request.get(a, function (error, response, body) {
var nextPlace = JSON.parse(body).place;
return callback(null, nextPlace); // null for no errors, and return the nextPlace to async
});
}
var recurse = function(startingPlace, callback2) {
request.get({
url: 'bbb'
}, function(error1, response1, body1) {
// store body somewhere outside these funtions
// make second request
request.get({
url: 'ccc'
}, function(error2, response2, body2) {
var anArray = JSON.parse(body2).stuff;
if (anArray) {
// The function that you want to call for each element of the array is `get`.
// So, prepare these calls, but you also need to pass different arguments
// and this is where `bind` comes into the picture and the link that I gave earlier.
var theParallelCalls = [];
for (var i = 0; i < anArray.length; i++) {
theParallelCalls.push(myGet.bind(null, {url: 'ddd'})); // Here, during the execution, parallel will pass its own callback as third argument of `myGet`; this is why we have callback and callback2 in the code
}
// Now perform the parallel calls:
async.parallel(theParallelCalls, function (error3, results) {
// All the parallel calls have returned
for (var i = 0; i < results.length; i++) {
var nextPlace = results[i];
recurse(nextPlace, callback2);
}
});
} else {
return callback2(null);
}
});
});
};
请注意,我假设对“bbb”的get
请求始终跟在对“ccc”的get
请求之后。换句话说,您没有在有评论的地方隐藏递归调用的返回点。
关于javascript - Node.js 的异步调用和递归,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26515671/