jQuery adia e promises -. then () vs .done ()

Eu tenho lido sobre adiamentos e promises do jQuery e não consigo ver a diferença entre usar .then() & .done() para retornos de chamada bem-sucedidos. Eu sei que Eric Hynds menciona que .done() e .success() mapeiam a mesma funcionalidade, mas acredito que o mesmo acontece com .then() já que todos os retornos de chamada são todos invocados na conclusão de uma operação bem-sucedida.

Alguém por favor pode me esclarecer sobre o uso correto?

Muito Obrigado

Os retornos de chamada anexados ao done() serão acionados quando o adiado for resolvido. Os retornos de chamada anexados ao fail() serão acionados quando o diferido for rejeitado.

Antes do jQuery 1.8, then() era apenas açúcar sintático:

 promise.then( doneCallback, failCallback ) // was equivalent to promise.done( doneCallback ).fail( failCallback ) 

A partir de 1.8, then() é um alias para pipe() e retorna uma nova promise, veja aqui para mais informações sobre pipe() .

success() e error() só estão disponíveis no object jqXHR retornado por uma chamada para ajax() . Eles são aliases simples para done() e fail() respectivamente:

 jqXHR.done === jqXHR.success jqXHR.fail === jqXHR.error 

Além disso, done() não está limitado a um único retorno de chamada e filtrará as não-funções (embora haja um bug com sequências na versão 1.8 que deve ser corrigido no 1.8.1):

 // this will add fn1 to 7 to the deferred's internal callback list // (true, 56 and "omg" will be ignored) promise.done( fn1, fn2, true, [ fn3, [ fn4, 56, fn5 ], "omg", fn6 ], fn7 ); 

O mesmo vale para o fail() .

Também há diferença no modo como os resultados de retorno são processados ​​(seu chamado encadeamento, done não encadeia enquanto produz cadeias de chamadas)

 promise.then(function (x) { // Suppose promise returns "abc" console.log(x); return 123; }).then(function (x){ console.log(x); }).then(function (x){ console.log(x) }) 

Os seguintes resultados serão registrados:

 abc 123 undefined 

Enquanto

 promise.done(function (x) { // Suppose promise returns "abc" console.log(x); return 123; }).done(function (x){ console.log(x); }).done(function (x){ console.log(x) }) 

receberá o seguinte:

 abc abc abc 

———- Atualização:

Btw. Eu esqueci de mencionar, se você retornar um Promise ao invés do valor do tipo atômico, a promise externa irá esperar até que a promise interna seja resolvida:

 promise.then(function (x) { // Suppose promise returns "abc" console.log(x); return $http.get('/some/data').then(function (result) { console.log(result); // suppose result === "xyz" return result; }); }).then(function (result){ console.log(result); // result === xyz }).then(function (und){ console.log(und) // und === undefined, because of absence of return statement in above then }) 

Desta forma, torna-se muito simples de compor operações assíncronas paralelas ou seqüenciais, tais como:

 // Parallel http requests promise.then(function (x) { // Suppose promise returns "abc" console.log(x); var promise1 = $http.get('/some/data?value=xyz').then(function (result) { console.log(result); // suppose result === "xyz" return result; }); var promise2 = $http.get('/some/data?value=uvm').then(function (result) { console.log(result); // suppose result === "uvm" return result; }); return promise1.then(function (result1) { return promise2.then(function (result2) { return { result1: result1, result2: result2; } }); }); }).then(function (result){ console.log(result); // result === { result1: 'xyz', result2: 'uvm' } }).then(function (und){ console.log(und) // und === undefined, because of absence of return statement in above then }) 

O código acima emite duas solicitações http em paralelo, concluindo assim as solicitações mais rapidamente, enquanto que abaixo dessas solicitações http estão sendo executadas em sequência, reduzindo assim a carga do servidor

 // Sequential http requests promise.then(function (x) { // Suppose promise returns "abc" console.log(x); return $http.get('/some/data?value=xyz').then(function (result1) { console.log(result1); // suppose result1 === "xyz" return $http.get('/some/data?value=uvm').then(function (result2) { console.log(result2); // suppose result2 === "uvm" return { result1: result1, result2: result2; }; }); }); }).then(function (result){ console.log(result); // result === { result1: 'xyz', result2: 'uvm' } }).then(function (und){ console.log(und) // und === undefined, because of absence of return statement in above then }) 

.done() tem apenas um retorno de chamada e é o retorno de chamada de sucesso

.then() tem callbacks de sucesso e falha

.fail() tem apenas um retorno de chamada com falha

então cabe a você o que você deve fazer … você se importa se for bem-sucedido ou se falhar?

deferred.done ()

adiciona manipuladores para serem chamados apenas quando Deferred for resolvido . Você pode adicionar vários retornos de chamada a serem chamados.

 var url = 'http://jsonplaceholder.typicode.com/posts/1'; $.ajax(url).done(doneCallback); function doneCallback(result) { console.log('Result 1 ' + result); } 

Você também pode escrever acima assim,

 function ajaxCall() { var url = 'http://jsonplaceholder.typicode.com/posts/1'; return $.ajax(url); } $.when(ajaxCall()).then(doneCallback, failCallback); 

deferred.then ()

adiciona manipuladores para serem chamados quando Deferred for resolvido, rejeitado ou ainda em andamento .

 var url = 'http://jsonplaceholder.typicode.com/posts/1'; $.ajax(url).then(doneCallback, failCallback); function doneCallback(result) { console.log('Result ' + result); } function failCallback(result) { console.log('Result ' + result); } 

Na verdade, existe uma diferença bastante crítica, na medida em que os Deferreds do jQuery devem ser implementações do Promises (e o jQuery3.0 realmente tenta trazê-los para o spec).

A principal diferença entre o feito / então é que

  • .done() SEMPRE retorna os mesmos valores Promise / wrapped com os quais começou, independentemente do que você faz ou do que retorna.
  • .then() sempre retorna uma NOVA Promessa, e você está encarregado de controlar o que essa Promessa é baseada na function que você retornou.

Traduzido do jQuery para o nativo ES2015 Promessas, .done() é uma espécie de implementação de uma estrutura “tap” em torno de uma function em uma cadeia Promise, na medida em que, se a cadeia estiver no estado “resolve”, passará um valor para uma function … mas o resultado dessa function NÃO afetará a própria cadeia.

 const doneWrap = fn => x => { fn(x); return x }; Promise.resolve(5) .then(doneWrap( x => x + 1)) .then(doneWrap(console.log.bind(console))); $.Deferred().resolve(5) .done(x => x + 1) .done(console.log.bind(console)); 

Aqueles vão registrar 5, não 6.

Note que eu usei done e doneWrap para fazer logging, não .depois. Isso porque as funções do console.log não retornam nada. E o que acontece se você passar. Então, uma function que não retorna nada?

 Promise.resolve(5) .then(doneWrap( x => x + 1)) .then(console.log.bind(console)) .then(console.log.bind(console)); 

Isso irá registrar:

5

Indefinido

O que aconteceu? Quando eu usei. Then e passei uma function que não retornou nada, o resultado implícito foi “indefinido” … o que naturalmente retornou um Promise [undefined] para o próximo método, que logou indefinido. Então o valor original com o qual começamos foi basicamente perdido.

.then() é, no fundo, uma forma de composição de funções: o resultado de cada passo é usado como argumento para a function na próxima etapa. É por isso que “feito” é melhor pensado como um “toque” -> não é realmente parte da composição, apenas algo que dá uma olhada no valor em uma determinada etapa e executa uma function nesse valor, mas na verdade não altera a composição de qualquer forma.

Esta é uma diferença bem fundamental, e há provavelmente uma boa razão pela qual os Promises nativos não implementaram um método próprio. Nós não precisamos entrar no porque não existe um método .fail, porque isso é ainda mais complicado (ou seja, .fail / .catch NÃO são espelhos de .done / .then -> funções em .catch que retornam valores nus não “ficar” rejeitado como aqueles passados ​​para. então, eles resolvem!)

then() sempre significa que será chamado em qualquer caso. Mas os parâmetros que passam são diferentes em diferentes versões do jQuery.

Antes do jQuery 1.8, then() é igual a done().fail() . E todas as funções de retorno de chamada compartilham os mesmos parâmetros.

Mas a partir do jQuery 1.8, then() retorna uma nova promise, e se ela retornar um valor, ela será passada para a próxima function de retorno de chamada.

Vamos ver o seguinte exemplo:

 var defer = jQuery.Deferred(); defer.done(function(a, b){ return a + b; }).done(function( result ) { console.log("result = " + result); }).then(function( a, b ) { return a + b; }).done(function( result ) { console.log("result = " + result); }).then(function( a, b ) { return a + b; }).done(function( result ) { console.log("result = " + result); }); defer.resolve( 3, 4 ); 

Antes do jQuery 1.8, a resposta deveria ser

 result = 3 result = 3 result = 3 

Todo result leva 3. E a function then() sempre passa o mesmo object adiado para a próxima function.

Mas a partir do jQuery 1.8, o resultado deve ser:

 result = 3 result = 7 result = NaN 

Porque a primeira function then() retorna uma nova promise, e o valor 7 (e este é o único parâmetro que será passado) é passado para o próximo done() , então o segundo done() escreve result = 7 . O segundo then() toma 7 como o valor de a e assume undefined como o valor de b , então o segundo then() retorna uma nova promise com o parâmetro NaN, e o último done() imprime NaN como resultado.

Existe um mapeamento mental muito simples em resposta que foi um pouco difícil de encontrar nas outras respostas:

  • implementos done tap como em Promises bluebird

  • then implementa then como no ES6 promises

.done() encerra a cadeia de promises, assegurando que nada mais possa append etapas adicionais. Isso significa que a implementação da promise do jQuery pode lançar qualquer exceção não tratada, já que ninguém pode manipulá-la usando .fail() .

Em termos práticos, se você não planeja append mais etapas a uma promise, você deve usar .done() . Para mais detalhes veja por que as promises precisam ser feitas