Reputation: 7285
I'm building something using node.js and I'm looping through all img
tags using jQuery .each()
. After all callbacks .each()
initiates are done I'll have the value I need in foo
.
var foo = -1;
window.each(function() {
// abracadabra
if (baz) foo = bar;
});
return foo; // this returns the incorrect foo as not all callbacks are complete
How do I get around this?
One way to do it is have an infinite loop that keeps checking the count of callbacks and when all are complete return foo
. I feel that's a bit hack-ish and there would be something better?
var allCallbacksDone = false;
var foo = -1;
window.each(function(index, element) {
// abracadabra
if (baz) foo = bar;
if (index == window.length - 1) allCallbacksDone = true;
});
while (!allCallbacksDone) {
continue;
}
return foo;
abracadabra
is a GET request to download remote images which is async.
Upvotes: 0
Views: 637
Reputation: 339786
YOU CANNOT RETURN VALUES FROM FUNCTIONS WHICH DEPEND ON THE RESULT OF ASYNCHRONOUS CALLS
Sorry about the shouting, but it had to be said...
The best you can do is to have another callback be invoked once all of the others are done.
Anything else will result in busy loops., which will make the application non-responsive.
To resolve this (no pun intended), use jQuery's deferred
objects:
var defArray = [];
window.each(function(index, element) {
// create a deferred object and store it
var d = $.Deferred();
defArray.push(d);
// trigger the image download
however you do it...
// register a callback for the download completion
// which "resolves" the deferred object
someimg.onload = function() {
d.resolve();
// probably other actions needed here too
}
});
// now call _another_ function once _all_ of the deferreds are resolved
$.when.apply($, defArray).then(function() {
// everything is done - do your calculations
});
Note that my first line still stands - you can't just wait for everything and then return the result - JS doesn't work that way.
Ideally you would create one addition deferred object, and your function return a promise
based on that object, which your final callback will resolve
with the result of the final calculation.
Upvotes: 4
Reputation: 954
Try this:
function check(callback) {
var foo = -1, complete = false, count = window.length - 1, interval;
window.each(function (index) {
if (baz) foo = bar;
complete = (index == count);
});
interval = setInterval(function () {
if (complete) {
clearInterval(interval);
callback();
}
}, 20);
}
Call check()
to run the .each()
loop, providing a method as callback
for when the task is complete.
Upvotes: 0
Reputation: 26143
Try this...
var foo = -1; // Don't need this now
var count = window.length;
window.each(function() {
// abracadabra
count--;
if (count == 0) complete(bar);
});
function complete(value) {
// everything is complete and value == bar
}
Upvotes: 0