Run function after another one completes
Solution 1
Try this,
$.when($.ajax(fuction1())).then(function () {
fuction2;
});
Here fuction1 is your first function to call, and fuction2 is your second function.
Solution 2
Either you take the promise approach, or you take the callback approach.
With callbacks, you'd pass function2
as a parameter to function1
;
function1 = function(callback){
something.on('transitionend', function(){
callback();
});
}
function2 = function(){
alert('ok');
}
function1(function2);
... but then you get nested-hell if you have function3
dependant on function2
, and function4
dependant on 3.
This is why you'd go down the deferred route;
function1 = function(){
var def = new jQuery.Deferred();
something.on('transitionend', function(){
def.resolve(arguments);
});
return def.promise();
}
function2 = function(){
alert('ok');
}
function1().done(function2);
... which would allow you to chain successive functions rather than nesting them (providing they all returned promises, of course).
Combining event handlers and deferreds is a bit messy. So if you went down the route of having multiple event handlers, you'd end up having to do something lame such as;
function1 = function(){
var def = new jQuery.Deferred();
var wait = 4;
function maybeFire() {
if (--wait) {
def.resolve();
}
}
something.on('transitionend', maybeFire);
something.on('somethingelse', maybeFire);
something.on('somethingelse', maybeFire);
something.on('somethingelse', maybeFire);
return def.promise();
}
function2 = function(){
alert('ok');
}
function1().done(function2);
The real way of combining multiple deferreds is by using $.when()
, but unfortunately here you don't have multiple deferreds, and adding them will be as messy as using the maybeFire
approach.
Solution 3
Note, transitionend
event may fire multiple times if all
is set within css
transition
property value
Try (this pattern)
i.e.g.,
html
<button>click</button>
css
button {
width: 100px;
-webkit-transition: width 1s;
}
.transition {
width: 150px
}
js
$(function() {
// `$.Callbacks("once")` to fire `alert` once ,
// even if `all` set within `css` `transition`
// property value
var callbacks = $.Callbacks();
function2 = function(j) {
alert(j);
};
callbacks.add(function2);
$(window).on("transitionComplete", function(e, i) {
// function2(i);
callbacks.fireWith($(this), [i]);
});
// `webkitTransitionEnd transitionend msTransitionEnd oTransitionEnd`
function1 = function() {
$("button").on('transitionend', function (e) {
$(window).trigger("transitionComplete", ["ok"]);
});
};
function1();
$("button").on("click", function(e) {
$(this).toggleClass("transition");
});
});
jsfiddle http://jsfiddle.net/guest271314/u7B9K/
Comments
-
thelolcat almost 2 years
function1 = function(){ something.on('transitionend', function(){ // now function2 should run }); } function2 = function(){ alert('ok'); } function1(); function2();
So I heard about jQuery promises. I would return a "deferred" object, and inside the event handler I would call deferred.resolve();
But what happens if i have multiple event handlers there and I only want the next function to run when all have been fired? + I don't like the idea of introducing something foreign like "deferred" into other parts of the code.
Is there any other way to detect if function1 has finished all its work?
-
Abram about 9 yearsFor what it's worth, I tried using this and it was causing my page to reload .. which in my case meant 3 calls to the geolocator api