I run multiple animations and perform some action when they're plete, using jQuery promises
:
$.when(foo(),
bar(),
baz())
.done(allDone);
Each function (foo
, etc.) returns a jQuery.Promise()
.
Now say I want to include a function which doesn't animate anything, but its timing is related to the animations - I can't include it in the chain, as it doesn't return a promise.
So I can hack it like so:
function qux() {
if (something) {
return $(".whatever")
.removeClass("bob")
.addClass("fred")
.append(/*...do stuff...*/)
.animate({ left: "+=0" }, 0, callback ) // <-- dummy animation does nothing
.promise(); // <-- this is a dummy promise
}
else {
return $().promise(); // <-- this is an "empty" promise
}
}
And now I can chain it:
$.when(foo(),
bar(),
baz(),
qux())
.done(allDone);
This works. But I'm bending the rules here - are there any gotchas I haven't taken into account, or am I somehow stomping on the fx queue?
UPDATE
As per answers below, the qux()
function can be rewritten as:
function qux() {
if (something) {
$(".whatever")
.removeClass("bob")
.addClass("fred")
.append(/*...do stuff...*/);
}
}
I run multiple animations and perform some action when they're plete, using jQuery promises
:
$.when(foo(),
bar(),
baz())
.done(allDone);
Each function (foo
, etc.) returns a jQuery.Promise()
.
Now say I want to include a function which doesn't animate anything, but its timing is related to the animations - I can't include it in the chain, as it doesn't return a promise.
So I can hack it like so:
function qux() {
if (something) {
return $(".whatever")
.removeClass("bob")
.addClass("fred")
.append(/*...do stuff...*/)
.animate({ left: "+=0" }, 0, callback ) // <-- dummy animation does nothing
.promise(); // <-- this is a dummy promise
}
else {
return $().promise(); // <-- this is an "empty" promise
}
}
And now I can chain it:
$.when(foo(),
bar(),
baz(),
qux())
.done(allDone);
This works. But I'm bending the rules here - are there any gotchas I haven't taken into account, or am I somehow stomping on the fx queue?
UPDATE
As per answers below, the qux()
function can be rewritten as:
function qux() {
if (something) {
$(".whatever")
.removeClass("bob")
.addClass("fred")
.append(/*...do stuff...*/);
}
}
Share
Improve this question
edited Jul 30, 2014 at 11:45
Bobby B
asked Jul 30, 2014 at 8:53
Bobby BBobby B
2,3253 gold badges25 silver badges48 bronze badges
8
- As per @YuryTarabanko answer, empty promise is unnecessary: "If a single argument is passed to jQuery.when and it is not a Deferred or a Promise, it will be treated as a resolved Deferred and any doneCallbacks attached will be executed immediately.". I suppose it works for the multi-argument case too. – Bobby B Commented Jul 30, 2014 at 9:15
-
1
Yes, it works for the multiple argument case, and also with real promises such as Bluebird or native promises using
Promise.all
. – Benjamin Gruenbaum Commented Jul 30, 2014 at 9:18 - 1 I would still return an empty promise if I were you, a function should always either return a promise or not. Not doing so is an inconsistent interface in my opinion since calling it should always represent an asynchronous operation. – Benjamin Gruenbaum Commented Jul 30, 2014 at 9:37
- @BenjaminGruenbaum check the edit, you mean like that? – Bobby B Commented Jul 30, 2014 at 11:45
-
This is definitely not what I meant. I meant I would not return
undefined
.qux
should always return a promise and the type of promise should depend on what it does. Like in your initial version (theelse
is redundant). – Benjamin Gruenbaum Commented Jul 30, 2014 at 11:47
2 Answers
Reset to default 7If you are going to use it with $.when
you don't need to return an empty promise. $.when
can handle non promises. Demo.
function promise(flag) {
if(flag) {
var dfd = $.Deferred();
setTimeout(function(){
console.log('promise');
dfd.resolve();
}, 1000);
return dfd.promise();
}
console.log('promise');
}
$.when(promise(), promise(true), promise(), 15).done(function(){
console.log('Done');
});
And if you want to return an empty promise you can use $.Deferred().resolve().promise()
If your function is always synchronous - simply do not return a promise:
function qux() {
if (something) {
return $(".whatever")
.removeClass("bob")
.addClass("fred")
.append(/*...do stuff...*/);
}
}
You can still use it in $.when
but there is little point since it executes synchronously. You should not return promises from synchronous functions.
However, if your function is sometimes synchronous - it should always return a promise for consistency.
As I said in earlier ments - $.when
is perfectly fine with non-promises (it will treat them as promises). So functions that might return promises can be used with $.when
however if it is always synchronous it is redundant to do so.