O jQuery's Deferred
tem duas funções que podem ser usadas para implementar o encadeamento assíncrono de funções:
then()
deferred.then( doneCallbacks, failCallbacks ) Returns: Deferred
doneCallbacks Uma função, ou matriz de funções, chamada quando o Deferred é resolvido.
failCallbacks Uma função, ou matriz de funções, chamada quando o Deferred é rejeitado.
pipe()
deferred.pipe( [doneFilter] [, failFilter] ) Returns: Promise
doneFilter Uma função opcional que é chamada quando o Adiado é resolvido.
failFilter Uma função opcional que é chamada quando Deferred é rejeitado.
Eu sei que then()
já existe há pouco mais tempo pipe()
, o último deve adicionar algum benefício extra, mas qual é a diferença precisamente me escapa. Ambos usam praticamente os mesmos parâmetros de retorno de chamada, embora difiram no nome e a diferença entre retornar a Deferred
e retornar a Promise
parece pequena.
Eu li os documentos oficiais várias vezes, mas sempre os achei muito "densos" para realmente entender e a pesquisa encontrou muitas discussões sobre um recurso ou outro, mas não encontrei nada que realmente esclareça os diferentes Prós e contras de cada.
Então, quando é melhor usar then
e quando é melhor usar pipe
?
Adição
A excelente resposta de Felix realmente ajudou a esclarecer como essas duas funções diferem. Mas eu me pergunto se há momentos em que a funcionalidade de then()
é preferível à de pipe()
.
É evidente que pipe()
é mais poderoso do que then()
e parece que o primeiro pode fazer tudo o que o último pode fazer. Um motivo de uso then()
pode ser que seu nome reflete sua função como o término de uma cadeia de funções que processam os mesmos dados.
Mas há um caso de uso que requer then()
a devolução do original Deferred
que não pode ser feito pipe()
devido ao retorno de um novo Promise
?
fonte
Respostas:
Já que o jQuery 1.8
.then
se comporta da mesma forma que.pipe
:e
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 chamadadone
efail
. 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:
e você deseja calcular o mínimo e o máximo dos valores. Vamos supor que usamos dois
done
callbacks: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: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:Agora, vamos supor que você deseja desacoplar seu código e colocar essas duas chamadas Ajax dentro de uma função:
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, masnã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()
: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 :)
fonte
pipe
posso fazer uma filtragem quethen
não posso fazer. Mas, ao pesquisar esses tópicos no Google, parece que eles escolheram chamá-lo empipe
vez defilter
porque consideraram a filtragem como uma espécie de bônus extra que veio com ela, enquantopipe
indicava mais claramente seu verdadeiro propósito. Portanto, parece que deve haver outras diferenças além da filtragem. (Mais uma vez, admito que realmente não entendo o recurso de filtragem, mesmo com seus exemplos. Deveresult values;
serreturn values;
a propósito?).then()
s recebem os mesmos dadosresult
que você filtra a cada vez; enquanto no exemplo inferior, o.pipe()
remove alguns dos dados em seuresult
antes de transmiti-los, poisresult
os dois.then()
s subsequentes receberão?.pipe()
. Se o retorno de chamada retornar um objeto adiado, retornos de chamada subsequentes concluídos ou com falha serão registrados para esse objeto. Vou incluir outro exemplo. editar: em relação ao seu segundo comentário: sim.pipe()
enquantothen()
é mais como um nó folha no final dos quais você deve usar seus dados e não flui mais adiante, e que, apesar do fato de quethen()
retorna aDeferred
ele não é realmente usado / útil? Se estiver correto, pode ser útil esclarecer incluir algo como/* do something with "min"/"max" */
em cada "cláusula .then ()".Não há nenhum caso em que você DEVE usar
then()
overpipe()
. Você sempre pode optar por ignorar o valor quepipe()
será transmitido. Pode haver um leve impacto no desempenho para usopipe
- mas é improvável que importe.Portanto, pode parecer que você simplesmente sempre pode usar
pipe()
em ambos os casos. No entanto , ao usarpipe()
, você está comunicando a outras pessoas que estão lendo seu código (incluindo você, daqui a seis meses) que há alguma importância no valor de retorno. Se você o está descartando, está violando essa construção semântica.É como ter uma função que retorna um valor que nunca é usado: confuso.
Portanto, use
then()
quando você deve, epipe()
quando você deve ...fonte
$(function () { $.when(getPosition()) .pipe(lookupCountry) .then(displayResults); });
"Observe que o tubo é diferente de então, porque o cachimbo devolve uma nova promessa. "Na verdade, descobriu-se que a diferença entre
.then()
e.pipe()
foi considerada desnecessária e eles foram considerados iguais aos da versão 1.8 do jQuery.De um comentário feito
jaubourg
no tíquete do rastreador de bug da jQuery # 11010 "MAKE DEFERRED.THEN == DEFERRED.PIPE LIKE PROMISE / A":(ênfase é minha)
fonte