Angular HttpPromise: diferença entre os métodos `success` /` error` e os argumentos do `then`

177

De acordo com o documento do AngularJS , as chamadas para $httpretornar o seguinte:

Retorna um objeto de promessa com o método then standard e dois métodos específicos de http: sucesso e erro . O método then recebe dois argumentos: um sucesso e um retorno de chamada de erro que será chamado com um objeto de resposta. Os métodos de sucesso e erro usam um único argumento - uma função que será chamada quando a solicitação for bem-sucedida ou falhar, respectivamente. Os argumentos passados ​​para essas funções são uma representação desestruturada do objeto de resposta passado para o método then.

Além do fato de o responseobjeto ser destruído em um caso, não entendo a diferença entre

  • os retornos de chamada de sucesso / erro passaram a ser passados ​​como argumentos de promise.then
  • os retornos de chamada transmitidos como argumentos para os promise.success/ promise.errormétodos da promessa

Existe algum? Qual é o objetivo dessas duas maneiras diferentes de transmitir retornos de chamada aparentemente idênticos?

ejoubaud
fonte

Respostas:

156

Nota: esta resposta está incorreta de fato; como apontado por um comentário abaixo, success () retorna a promessa original. Não vou mudar; e deixe para OP para editar.


A principal diferença entre os 2 é que a .then()chamada retorna uma promessa (resolvida com um valor retornado de um retorno de chamada), enquanto .success()é a maneira mais tradicional de registrar retornos de chamada e não retorna uma promessa.

Retornos de chamada baseados em Promise ( .then()) torná-lo fácil de promessas cadeia (fazer uma chamada, interpretar os resultados e , em seguida, fazer outra chamada, interpretar os resultados, fazer ainda outra chamada etc.).

O .success()método é um método simplificado e conveniente quando você não precisa encadear chamadas nem trabalhar com a API da promessa (por exemplo, no roteamento).

Em resumo:

  • .then() - poder total da API da promessa, mas um pouco mais detalhado
  • .success() - não retorna uma promessa, mas oferece uma sintaxe um pouco mais conveniente
pkozlowski.opensource
fonte
44
Outra grande diferença é que os thenretornos de chamada tirar um único argumento - a resposta - enquanto successe errorter componentes individuais da resposta como arguments-- data, status, header, e config.
Michelle Tilley
1
@BrandonTilley totalmente certo, mas o autor da pergunta já descobriu isso, então não senti que precisava repeti-la aqui.
Pkozlowski.opensource
45
Embora a documentação não diga isso explicitamente, podemos inferir que o .success()método retorna o objeto de promessa $ http original, pois a cadeia $http(...).success(...).error(...)é possível. Se, como parece razoável, o inverso $http(...).error(...).success(...)também for possível, .error()deverá também retornar o objeto de promessa original. A diferença distintiva .then()é que ela retorna uma nova promessa.
Beterrabas-Beterrabas
2
Código-fonte angular.js do serviço $ http:promise.success = function(fn) { promise.then(function(response) { fn(response.data, response.status, response.headers, config); }); return promise; };
Alex Che
6
Observe que successfoi preterido. De docs.angularjs.org/api/ng/service/$http#deprecation-notice The $http legacy promise methods success and error have been deprecated. Use the standard then method instead. If $httpProvider.useLegacyPromiseExtensions is set to false then these methods will throw $http/legacy error.
Sam Barnum
204

Já existem algumas boas respostas aqui. Mas vale a pena ressaltar a diferença de paralelismo oferecida:

  • success() retorna a promessa original
  • then() retorna uma nova promessa

A diferença está nas then()operações seqüenciais, pois cada chamada retorna uma nova promessa.

$http.get(/*...*/).
  then(function seqFunc1(response){/*...*/}).
  then(function seqFunc2(response){/*...*/})
  1. $http.get()
  2. seqFunc1()
  3. seqFunc2()

success() dirige operações paralelas, já que os manipuladores são encadeados com a mesma promessa.

$http(/*...*/).
  success(function parFunc1(data){/*...*/}).
  success(function parFunc2(data){/*...*/})
  1. $http.get()
  2. parFunc1(), parFunc2()Em paralelo
event_jr
fonte
3
Observe que a nova resposta de promessa retornada quando a thené atingida resulta nos métodos successe errordesaparecendo. Além disso, para http respostas de erro (por exemplo, 404) a primeira thenno http.then(ok, err).then(ok, err)vai passar para o errmanipulador, mas os seguintes passará para o okmanipulador. Basicamente, http.success().error().success().error()são encadeados, mas as promessas $ q são bem diferentes, pois tratam especificamente da promessa e da sequência de manipulação (e não da manipulação de solicitações http). Eu tive dificuldade para entender isso até olhar de perto.
jimmont
1
@ jimmont successe errornão são uma API normal de uma promessa, eles são aparafusados ​​no valor de retorno de $ http ().
event_jr
Obrigado @event_jr, isso está claro para mim e foi mencionado nos documentos. O que não ficou tão claro (para mim) é como $ q e $ http resolvem problemas diferentes, além de retornar novas promessas vs passar a mesma - como indicado na sua resposta (super útil).
precisa saber é o seguinte
1
O que você quer dizer com paralelo, já que JS é de thread único? Você quer dizer que a ordem de execução é não determinística?
Drek
2
@Derek o segundo successserá executado depois que o primeiro for executado, mas antes que qualquer promessa retornada seja resolvida, enquanto o segundo thenaguardará. Se você não está retornando promessas, ambos se comportam da mesma forma.
Tamlyn
114

Alguns exemplos de código para solicitação GET simples. Talvez isso ajude a entender a diferença. Usando then:

$http.get('/someURL').then(function(response) {
    var data = response.data,
        status = response.status,
        header = response.header,
        config = response.config;
    // success handler
}, function(response) {
    var data = response.data,
        status = response.status,
        header = response.header,
        config = response.config;
    // error handler
});

Usando success/ error:

$http.get('/someURL').success(function(data, status, header, config) {
    // success handler
}).error(function(data, status, header, config) {
    // error handler
});
TheHippo
fonte
5
Obrigado, mas a pergunta era mais sobre a diferença no que essas funções fazem ou o motivo pelo qual ambas existem, se fazem a mesma coisa. A diferença de como usá-los é compreensível no documento.
Ejoubaud
39
Eu, pessoalmente, gosto de exemplos de códigos curtos, e os publiquei aqui. Os documentos angulares às vezes perdem exemplos curtos e precisos.
TheHippo
2
É importante destacar o fato de que o objeto de resposta da primeira essência contém "dados, status, heade e configuração" da segunda essência. Isso significa que os objetos de resposta têm um nível adicional de profundidade.
Geoom 22/05
Existe algum benefício em passar os valores de resposta para as variáveis ​​em data,status,header,configvez de simplesmente retornar response?
ᴍᴀᴛᴛ ʙᴀᴋᴇʀ
27

.then () pode ser encadeado e aguardará a resolução .then () anterior.

.success () e .error () podem ser encadeados, mas todos serão acionados ao mesmo tempo (portanto, não há muito sentido nisso)

.success () e .error () são ótimos para chamadas simples (fabricantes fáceis):

$http.post('/getUser').success(function(user){ 
   ... 
})

então você não precisa digitar isso:

$http.post('getUser').then(function(response){
  var user = response.data;
})

Mas geralmente manipulo todos os erros com .catch ():

$http.get(...)
    .then(function(response){ 
      // successHandler
      // do some stuff
      return $http.get('/somethingelse') // get more data
    })
    .then(anotherSuccessHandler)
    .catch(errorHandler)

Se você precisar oferecer suporte ao <= IE8, escreva seu .catch () e .finally () assim (métodos reservados no IE):

    .then(successHandler)
    ['catch'](errorHandler)

Exemplos de trabalho:

Aqui está algo que eu escrevi em um formato mais codey para atualizar minha memória sobre como tudo acontece com a manipulação de erros, etc:

http://jsfiddle.net/nalberg/v95tekz2/

nawlbergs
fonte
A única resposta que mostra como o "retorno-outra-promessa" funciona
ZJK
17

Apenas para conclusão, aqui está um exemplo de código indicando as diferenças:

sucesso \ erro:

$http.get('/someURL')
.success(function(data, status, header, config) {
    // success handler
})
.error(function(data, status, header, config) {
    // error handler
});

então:

$http.get('/someURL')
.then(function(response) {
    // success handler
}, function(response) {
    // error handler
})
.then(function(response) {
    // success handler
}, function(response) {
    // error handler
})
.then(function(response) {
    // success handler
}, function(response) {
    // error handler
}).
MichaelLo
fonte
ótimo !, você tem um exemplo em que a concatenação pode ser útil?
Geoom 22/05
4
A idéia é que a abordagem "then" seja mais útil, pois você pode escrever operações assíncronas mais facilmente, uma após a outra.
MichaelLo
2

Aviso oficial: o sucesso e o erro foram preteridos. Em vez disso, use o método padrão.

Aviso de descontinuação: o sucesso e o erro dos métodos de promessa herdada $ http foram descontinuados. Use o método padrão e, em vez disso. Se $ httpProvider.useLegacyPromiseExtensions estiver definido como false, esses métodos gerarão um erro $ http / legacy.

link: https://code.angularjs.org/1.5.7/docs/api/ng/service/$http

captura de tela: veja a captura de tela

MagicBoy
fonte