Exemplos de $.when()

Atualizaçao: Mais exemplos e completão.

Caso Simples: dois ajax ao mesmo tempo

90% das vezes é isso que a gente precisa.

1
2
3
4
5
6
7
$.when(
  $.ajax('/value1'),
  $.ajax('/value2'))
.done(function (data1, data2) {
  console.log('os dois ajax terminaram');
  console.log('agora dá para chamar alguma função que usa as duas respostas dos ajax');
});

Muito prático, por exemplo para carregar um html, os dados necessários para preenchê-lo e depois inserir na página.

O que acontece é que o $.when recebe como parâmetros objetos chamados
Deferreds“, uma tradução seria “adiados”, ou seja, objetos que não retornam
imediatamente, são adiados, em algum momento “prometem” que irão terminar.

Quando as promises terminam o “done” é executado.

Outros Exemplos

Grande parte dos erros que acontecem ao usar $.when() são por usar alguma função que não retorna uma promise.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
function getFacebookData() {
  // criamos uma deferred para resolver somente quando termina o FB
  var dfd = new $.Deferred();

  // o FB acontece async e não retorna uma promise
  FB.api('/me', {fields: 'last_name'}, function(response) {
    console.log(response);

    // aqui avisamos ao $.when que  o FB terminou
    dfd.resolve(response);
  });

  // retorna ao $.when uma promessa de que em algum momento a função vai terminar
  return dfd.promise();
}

function getTimeout() {
  // criamos uma deferred para resolver somente quando terminar o timeout
  var dfd = new $.Deferred();

  setTimeout(function() {
    // alguma coisa complexa acontecendo aqui

    // avisa ao $.when que terminou o getTimeout()
    dfd.resolve("fim");
  }, 1000);

  // retorna ao $.when uma promessa de que em algum momento a função vai terminar
  return dfd.promise();
}

// $.ajax retorna uma promise, mas não uma função com $.ajax dentro
function complexAjax(x) {
  var options = {
    url: '/url1',
    data: { param1: x }
  }

  // não é necessário criar a dfd aqui,
  // podemos retornar a própria promise do ajax
  return $.ajax(options);
}

$.when(
  getFacebookData(),
  getTimeout(),
  complexAjax('teste')
.done(function (fbResponse, dataFromTimeout, ajaxData) {
  // as funções terminaram
});

Muitas funções do jQuery retornam uma promise, $.ajax() e $.animate() por exemplo.
Quando uma função não retorna a promessa, como o FB, podemos simplesmente criar uma e retornar quando quisermos.

 

Esse foi um resumão do funcionamento das deferreds, eu estava escrevendo um tutorial mas estava ficando muito grande, acho que os exemplos acima já resolvem muitos problemas, depois eu posto o completão com detalhes de Promise, Deferreds, when, then, done, async, etc.

Referências

Deferreds – http://api.jquery.com/jQuery.Deferred/

$.when – http://api.jquery.com/jquery.when/