I'm looking to execute a callback upon the full completion of a recursive function that can go on for an undetermined amount of time. I'm struggling with async issues and was hoping to get some help here. The code, using the request
module, is as follows:
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();
});
It seems that once my code goes past the for
loop in the nested requests, it continues out of the request and ends the initial function call while the recursive calls are still going on. I want it to not finish the highest-level iteration until all the nested recursive calls have completed (which I have no way of knowing how many there are).
Any help is GREATLY appreciated!
Typically when you write a recursive function it will do something and then either call itself or return.
You need to define
callback
in the scope of the recursive function (i.e.recurse
instead ofstart
), and you need to call it at the point where you would normally return.So, a hypothetical example would look something like:
In your example you have no recursive calls. If I understand correctly you want to say that
recurse(point, otherFunc);
is the beginning of a recursive call.Then just go back to the definition of the recursive call (which you have not shown in your post) and do this (add a third argument for a callback function to be called in the end of recursion; the caller will pass it as a parameter):
Then in the original code that you posted, make this call instead (in the inner-most part):
Just spend some time and try to understand my explanation. When you understand, then you will know node. This is the node philosophy in one post. I hope it is clear. Your very first example should look like this:
Below is only additional information in case you are interested. Otherwise you are set with the above.
Typically in node.js though, people return an error value as well, so that the caller knows if the function that was called has finished successfully. There is no big mystery here. Instead of returning just
results
people make a call of the formThen in the other function you can have:
Update with my suggestion
This is my suggestion for the recursive function, but before that, it looks like you need to define your own
get
:Note that I assume that the
get
request for 'bbb' is always followed by aget
request for 'ccc'. In other words, you have not hidden a return point for the recursive calls where you have the comments.Build your code from this example:
If your recursive function is synchronous, just call the callback on the next line:
Else you need to keep a reference to the callback in your recursive function.
Pass the callback as an argument to the function and call it whenever it is finished.
I think you might find caolan/async useful. Look especially into
async.waterfall
. It will allow you to pass results from a callback from another and when done, do something with the results.Example: