Avo*_*lry 5 javascript recursion asynchronous node.js
我希望在完全完成递归函数后执行回调,该递归函数可以持续一段不确定的时间.我正在努力解决异步问题,希望能在这里得到一些帮助.使用该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();
});
Run Code Online (Sandbox Code Playgroud)
似乎一旦我的代码超过了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
}
Run Code Online (Sandbox Code Playgroud)
然后在您发布的原始代码中,改为进行此调用(在最内部):
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
});
Run Code Online (Sandbox Code Playgroud)
花一些时间试着理解我的解释.当你明白,那么你就会知道节点.这是一篇文章中的节点哲学.我希望很清楚.您的第一个示例应如下所示:
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();
});
});
};
Run Code Online (Sandbox Code Playgroud)
以下是您感兴趣的其他信息.否则,您将使用上述设置.
通常在node.js中,人们也返回错误值,以便调用者知道被调用的函数是否已成功完成.这里没有什么大不了的.而不是只返回results人们打电话的形式
return callback_one(null, val);
Run Code Online (Sandbox Code Playgroud)
然后在另一个功能中你可以:
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()
});
Run Code Online (Sandbox Code Playgroud)
更新我的建议
这是我对递归函数的建议,但在此之前,看起来你需要定义自己的函数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);
}
});
});
};
Run Code Online (Sandbox Code Playgroud)
请注意,我假设get'bbb'的get请求后面总是跟着'ccc' 的请求.换句话说,您没有为具有注释的递归调用隐藏返回点.
通常,当您编写递归函数时,它会执行某些操作,然后调用自身或返回.
您需要callback在递归函数的范围内定义(即recurse代替start),并且您需要在通常返回的位置调用它.
因此,一个假设的例子看起来像:
get_all_pages(callback, page) {
page = page || 1;
request.get({
url: "http://example.com/getPage.php",
data: { page_number: 1 },
success: function (data) {
if (data.is_last_page) {
// We are at the end so we call the callback
callback(page);
} else {
// We are not at the end so we recurse
get_all_pages(callback, page + 1);
}
}
}
}
function show_page_count(data) {
alert(data);
}
get_all_pages(show_page_count);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
23667 次 |
| 最近记录: |