Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using jquery deferred to sync animation and ajax

I'm trying to get my head around the whole deferred concept and I'm trying to use it to synchronize a fadeIn/fadeOut animation together with an Ajax call.

Basically I'm switching content on page doing:

  1. Fetch content with ajax
  2. On response FadeOut
  3. Replace content
  4. FadeIn

However, If i understand deferreds right I might be able to do something like this:

  1. fadeOut, and at the same time initialize Fetch content with ajax
  2. When both the fadeOut and the Fetch content are complete: Change content
  3. FadeIn

Some code of the original solution:

$.get(url, function(page) {
    $('#content').fadeTo(100, 0, 'linear', function() {
        $(this).html(page.text).fadeTo(400, 1, 'linear');
    });
}

I am trying to do something like this:

var deferred1 = $.get(url);
var deferred2 = $('#content').fadeTo(100, 0, 'linear').promise();

$.when(deferred1, deferred2).done(function() {
    $('#content').html(page.text).fadeTo(400, 1, 'linear');
});

I just can't really get clear on how to use it. And should i use done or then? Should I use pipe in a clever way? Do I need promise?

What would be the more 'standardized' way to implement this?

like image 397
Yonder Avatar asked Apr 12 '13 11:04

Yonder


1 Answers

When you use $.when (I know, funny sentence ;)), then the values with which the promises are resolved are passed as arguments to the callback functions. I.e. in your done callback, the first argument refers to the resolved value of deferred1 and the second argument to deferred2 (whatever that is).

Now, when an Ajax success callback is called, it gets passed three arguments:

  • the response
  • the status text
  • the jqXHR object

You are only interested in the first.

So with this, your setup should be:

var promise1 = $.get(url);
var promise2 = $('#content').fadeTo(100, 0, 'linear').promise();

$.when(promise1, promise2).done(function(ajax_success) {
    $('#content').html(ajax_success[0]).fadeTo(400, 1, 'linear');
});

Also have a look at the $.when documentation.


Do I need promise?

No. It looks like $.when calls .promise internally when you pass a jQuery collection. But in other cases you would have to, so it makes sense to do this here as well, for consistency (thanks Alnitak).

And should i ... ? Should I ...? What would be ...?

There is no standard solution for this kind of problems. Promises are incredibly flexible and there are so many ways to use. I think they are not around long enough in JavaScript for standard patterns to emerge. Find/create something that makes sense to you and be consistent within your application.

The only thing I would recommend to do if you have multiple promises is put them in an array: jQuery $.when() with variable arguments.

like image 173
Felix Kling Avatar answered Oct 05 '22 09:10

Felix Kling