Calling A Function After Another Function's Callbacks Are Returned
Solution 1:
The only way to make something like this work properly is to make y
asynchronous. Basically, y
internally waits for x
to complete before executing its own code. This is similar to things like domready
or onload
which waits for other things to happen before executing their own logic.
There are two ways to accomplish this. The first, simplest and most naive way is setTimeout
polling. Make x
set a variable or attribute and check that before executing:
function y () {
if (x.ready) {
/* do what you need to do here */
}
else {
setTimeout(y,100);
}
}
The second method is to create virtual events or promises. Not all promise libraries support using a promise that has already expired (my own homemade one does) so you may need to write your own control flow to handle that case. For this you need to rewrite x
to support an event or promise-like api:
var x = (function () {
var async_calls = 2;
var callback;
f = function () {
console.log('x is called');
async_call_one(function(){
async_calls --;
if (async_calls == 0 && callback) callback();
callback_one();
});
async_call_two(function(){
async_calls --;
if (async_calls == 0 && callback) callback();
callback_two();
});
}
f.loaded = function (loaded_callback) {
callback = loaded_callback;
if (async_calls == 0) callback();
}
return f;
})();
Now in y
you can use the x.loaded
function to execute your code when x is loaded:
functiony() {
x.loaded(function(){
/* do what you need to do here */
});
}
Of course, this has the problem of making y
asynchronous. Therefore if your users expect to write something like:
y();
a();
b();
then a
and b
may or may not execute before y
. To solve this you need to make y
accept a callback so that you users can control their program flow:
function y (callback) {
if (x.ready) {
/* do what you need to do here */callback();
}
else {
setTimeout(function(){y(callback)},100);
}
}
or:
functiony(callback) {
x.loaded(function(){
/* do what you need to do here */
callback();
});
}
So they'd have to use y
like this:
y(function(){
a();
b();
});
Alternatively you can make y
return a promise if you prefer that style.
Solution 2:
A little bit down the road to spaghetti code but you could wrap up the two callbacks together by setting variables they both can see and only call y() when they both return.
for example
var finished = false;
var aync_call_one = function () {
//stuffif (finished) {
y();
} else {
finished = true;
}
}
var aync_call_two = function () {
//stuffif (finished) {
y();
} else {
finished = true;
}
}
However if you have to use jquery promises, you need to return a promise object to use $.when,
var deferred = $.Deferred();
return deferred.promise();
and inside the asyncs you need to do
deferred.resolve();
though that would only work for one of your async calls so you would need another $.when inside the first function, so it can get sloppy quick.
Post a Comment for "Calling A Function After Another Function's Callbacks Are Returned"