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?
Try this,
$.when($.ajax(fuction1())).then(function () {
fuction2;
});
Here fuction1 is your first function to call, and fuction2 is your second function.
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.
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/