Já que o jQuery 1.8 .then
se comporta da mesma forma que .pipe
:
Aviso de suspensão de uso: a partir do jQuery 1.8, o deferred.pipe()
método está obsoleto. O deferred.then()
método, que o substitui, deve ser usado em seu lugar.
e
A partir do jQuery 1.8 , o deferred.then()
método retorna uma nova promessa que pode filtrar o status e os valores de um adiado por meio de uma função, substituindo o deferred.pipe()
método agora obsoleto .
Os exemplos abaixo ainda podem ser úteis para alguns.
Eles têm finalidades diferentes:
.then()
é para ser usado sempre que você quiser trabalhar com o resultado do processo, ou seja, como diz a documentação, quando o objeto diferido é resolvido ou rejeitado. É o mesmo que usar .done()
ou .fail()
.
Você usaria .pipe()
para (pré) filtrar o resultado de alguma forma. O valor de retorno de um retorno de chamada para .pipe()
será passado como argumento para os retornos de chamada done
e fail
. Ele também pode retornar outro objeto adiado e os seguintes callbacks serão registrados neste adiado.
Esse não é o caso com .then()
(ou .done()
, .fail()
), os valores de retorno dos retornos de chamada registrados são simplesmente ignorados.
Portanto, não é que você use tanto .then()
ou .pipe()
. Você poderia usar .pipe()
para os mesmos fins, .then()
mas o inverso não é válido.
Exemplo 1
O resultado de alguma operação é uma matriz de objetos:
[{value: 2}, {value: 4}, {value: 6}]
e você deseja calcular o mínimo e o máximo dos valores. Vamos supor que usamos dois done
callbacks:
deferred.then(function(result) {
// result = [{value: 2}, {value: 4}, {value: 6}]
var values = [];
for(var i = 0, len = result.length; i < len; i++) {
values.push(result[i].value);
}
var min = Math.min.apply(Math, values);
/* do something with "min" */
}).then(function(result) {
// result = [{value: 2}, {value: 4}, {value: 6}]
var values = [];
for(var i = 0, len = result.length; i < len; i++) {
values.push(result[i].value);
}
var max = Math.max.apply(Math, values);
/* do something with "max" */
});
Em ambos os casos, você deve iterar pela lista e extrair o valor de cada objeto.
Não seria melhor extrair os valores de alguma forma com antecedência para que você não tenha que fazer isso em ambos os retornos de chamada individualmente? Sim! E é isso que podemos usar .pipe()
para:
deferred.pipe(function(result) {
// result = [{value: 2}, {value: 4}, {value: 6}]
var values = [];
for(var i = 0, len = result.length; i < len; i++) {
values.push(result[i].value);
}
return values; // [2, 4, 6]
}).then(function(result) {
// result = [2, 4, 6]
var min = Math.min.apply(Math, result);
/* do something with "min" */
}).then(function(result) {
// result = [2, 4, 6]
var max = Math.max.apply(Math, result);
/* do something with "max" */
});
Obviamente, este é um exemplo inventado e há muitas maneiras diferentes (talvez melhores) de resolver esse problema, mas espero que ilustre o ponto.
Exemplo 2
Considere as chamadas Ajax. Às vezes, você deseja iniciar uma chamada Ajax após a conclusão de uma anterior. Uma maneira é fazer a segunda chamada dentro de um done
retorno de chamada:
$.ajax(...).done(function() {
// executed after first Ajax
$.ajax(...).done(function() {
// executed after second call
});
});
Agora, vamos supor que você deseja desacoplar seu código e colocar essas duas chamadas Ajax dentro de uma função:
function makeCalls() {
// here we return the return value of `$.ajax().done()`, which
// is the same deferred object as returned by `$.ajax()` alone
return $.ajax(...).done(function() {
// executed after first call
$.ajax(...).done(function() {
// executed after second call
});
});
}
Você gostaria de usar o objeto deferido para permitir que outro código que chama makeCalls
para anexar retornos de chamada para a segunda chamada Ajax, mas
makeCalls().done(function() {
// this is executed after the first Ajax call
});
não teria o efeito desejado, pois a segunda chamada é feita dentro de um done
retorno de chamada e não pode ser acessada externamente.
A solução seria usar .pipe()
:
function makeCalls() {
// here we return the return value of `$.ajax().pipe()`, which is
// a new deferred/promise object and connected to the one returned
// by the callback passed to `pipe`
return $.ajax(...).pipe(function() {
// executed after first call
return $.ajax(...).done(function() {
// executed after second call
});
});
}
makeCalls().done(function() {
// this is executed after the second Ajax call
});
Usando, .pipe()
agora você pode tornar possível anexar retornos de chamada à chamada Ajax "interna" sem expor o fluxo / ordem real das chamadas.
Em geral, os objetos adiados fornecem uma maneira interessante de desacoplar seu código :)