Angular HttpPromise: разница между методами `success` /` error` и аргументами `then`

Согласно AngularJS doc, вызовы $http возвращают следующее:

Возвращает обещание с помощью стандартного метода then и двух методов, специфичных для http: success и error. Метод then принимает два аргумента: успех и обратный вызов ошибка, которые будут вызываться с объектом ответа. Методы success и error принимают один аргумент - функцию, которая будет вызываться при успешном или неудачном выполнении запроса соответственно. Аргументы, передаваемые в эти функции, являются деструктурированным представлением объекта ответа, переданного в метод then.

Помимо того факта, что объект response деструктурируется в одном случае, я не вижу разницы между

  • переданные обратные вызовы успеха / ошибки для передачи в качестве аргументов promise.then
  • обратные вызовы, переданные как аргументы для _4 _ / _ 5_ методов обещания

Есть ли? В чем смысл этих двух разных способов передачи, казалось бы, идентичных обратных вызовов?


person ejoubaud    schedule 05.05.2013    source источник


Ответы (6)


NB Этот ответ фактически неверен; как указано в комментарии ниже, success () возвращает исходное обещание. Я не буду изменять; и оставьте его для редактирования OP.


Основное различие между 2 состоит в том, что вызов .then() возвращает обещание (разрешенное значением, возвращаемым из обратного вызова), в то время как .success() является более традиционным способом регистрации обратных вызовов и не возвращает обещание.

Обратные вызовы на основе обещаний (.then()) упрощают цепочку обещаний (выполнить вызов, интерпретировать результаты и затем выполнить еще один вызов, интерпретировать результаты, выполнить еще один вызов и т. Д.).

Метод .success() - это упрощенный и удобный метод, когда вам не нужно связывать вызовы или работать с API обещаний (например, при маршрутизации).

Суммируя:

  • .then() - полная мощь API обещаний, но немного более подробный
  • .success() - не возвращает обещание, но предлагает немного более удобный синтаксис
person pkozlowski.opensource    schedule 05.05.2013
comment
Еще одно большое отличие состоит в том, что обратные вызовы then принимают один аргумент - ответ, в то время как success и error принимают отдельные компоненты ответа в качестве аргументов --_ 4_, status, header и config. - person Michelle Tilley; 05.05.2013
comment
@BrandonTilley совершенно прав, но автор вопроса уже понял это, поэтому я не чувствовал, что мне нужно повторять это здесь. - person pkozlowski.opensource; 05.05.2013
comment
Хотя в документации это прямо не сказано, мы можем сделать вывод, что метод .success() возвращает исходный объект обещания $ http, поскольку возможна цепочка $http(...).success(...).error(...). Если, что кажется разумным, обратное $http(...).error(...).success(...) также возможно, тогда .error() также должен вернуть исходный объект обещания. Отличительное отличие .then() в том, что он возвращает новое обещание. - person Beetroot-Beetroot; 06.05.2013
comment
Итак, оба метода делают одно и то же, но предлагают несколько разные варианты цепочки. Ответ pkozlowski + исправление Beetroot кажется правильным ответом. Чтобы я мог принять ответ, пкозловски, не могли бы вы поправить свой? Или свекла, сделай свой собственный? - person ejoubaud; 06.05.2013
comment
Исходный код из angular.js службы $ http: promise.success = function(fn) { promise.then(function(response) { fn(response.data, response.status, response.headers, config); }); return promise; }; - person Alex Che; 28.11.2013
comment
Тот же исходный код для функции ошибки: обещание.error = функция (fn) {обещание.then (null, функция (ответ) {fn (response.data, response.status, response.headers, config);}); обещание возврата; }; поэтому он возвращает обещание - person David Michael Gang; 02.11.2014
comment
Обратите внимание, что success устарел. Из https://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. - person Sam Barnum; 17.02.2016

Здесь уже есть несколько хороших ответов. Но стоит обратить внимание на разницу в предлагаемом параллелизме:

  • success() возвращает исходное обещание
  • then() возвращает новое обещание

Разница в том, что then() управляет последовательными операциями, поскольку каждый вызов возвращает новое обещание.

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

success() управляет параллельными операциями, поскольку обработчики связаны одним и тем же обещанием.

$http(/*...*/).
  success(function parFunc1(data){/*...*/}).
  success(function parFunc2(data){/*...*/})
  1. $http.get()
  2. parFunc1(), parFunc2() параллельно
person event_jr    schedule 22.05.2014
comment
Обратите внимание, что новый ответ на обещание, возвращаемый после достижения then, приводит к исчезновению методов success и error. Кроме того, для ответов об ошибках http (например, 404) первый then в http.then(ok, err).then(ok, err) будет передан обработчику err, а следующие - обработчику ok. В основном http.success().error().success().error() объединяются в цепочки, но обещания $ q сильно отличаются тем, что все они касаются конкретно обещания и последовательности обработки (а не обработки HTTP-запросов). Мне было трудно понять это, пока я не присмотрелся. - person jimmont; 17.09.2014
comment
@jimmont success и error не являются обычным API обещания, они привязаны к возвращаемому значению $ http (). - person event_jr; 18.09.2014
comment
Спасибо @event_jr, это мне ясно и указано в документации. Что было не так ясно (для меня), так это то, как $ q и $ http решают разные проблемы, а также возвращают новые обещания и пропускают одно и то же - как указано в вашем (очень полезном) ответе. - person jimmont; 18.09.2014
comment
Что вы подразумеваете под параллельным, поскольку JS является однопоточным? Вы имеете в виду, что порядок выполнения недетерминированный? - person Derek; 03.03.2015
comment
@Derek, второй success будет выполняться после выполнения первого, но до того, как будет выполнено какое-либо обещание, возвращенное от него, тогда как второе then будет ждать. Если вы не возвращаете обещания, оба ведут себя одинаково. - person Tamlyn; 31.03.2015
comment
что делает функция then () с одной функцией обратного вызова? вызовите обратный вызов только при успехе? - person Benny; 05.05.2015
comment
Успех / ошибка устарели. Я считаю это хорошей вещью. Вот краткое изложение некоторых недостатков успеха: syntaxsuccess.com/viewarticle/ - person TGH; 05.08.2015

Некоторые примеры кода для простого запроса GET. Может быть, это поможет понять разницу. Использование 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
});

Использование _3 _ / _ 4_:

$http.get('/someURL').success(function(data, status, header, config) {
    // success handler
}).error(function(data, status, header, config) {
    // error handler
});
person TheHippo    schedule 05.05.2013
comment
Спасибо, но вопрос был больше о разнице в том, что делают эти функции, или о причине их существования, если они делают одно и то же. Разница в том, как их использовать, понятна из документа. - person ejoubaud; 06.05.2013
comment
Мне лично нравятся короткие примеры кода, и я разместил их здесь. В документации по Angular иногда не хватает коротких и точных примеров. - person TheHippo; 06.05.2013
comment
Важно подчеркнуть тот факт, что объект ответа первой сущности содержит данные, статус, заголовок и конфигурацию второй сущности. Это означает, что объекты ответа имеют дополнительный уровень глубины. - person geoom; 22.05.2014
comment
Есть ли какая-то польза от передачи значений ответа в переменные data,status,header,config по сравнению с простым возвратом response? - person ᴍᴀᴛᴛ ʙᴀᴋᴇʀ; 24.11.2015

.then () объединяется в цепочку и будет ждать разрешения предыдущего .then ().

.success () и .error () могут быть связаны в цепочку, но все они будут срабатывать одновременно (так что особого смысла в этом нет)

.success () и .error () удобны для простых вызовов (easy makers):

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

так что вам не нужно вводить это:

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

Но обычно я обрабатываю все ошибки с помощью .catch ():

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

Если вам нужно поддерживать ‹= IE8, напишите ваши .catch () и .finally () следующим образом (зарезервированные методы в IE):

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

Рабочие примеры:

Вот кое-что, что я написал в более кодированном формате, чтобы освежить мою память о том, как все это работает с ошибками и т. Д.:

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

person nawlbergs    schedule 12.12.2014
comment
Единственный ответ, который показывает, как работает return-another-prom - person zjk; 20.08.2015

В завершение, вот пример кода, указывающий на различия:

успех \ ошибка:

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

тогда:

$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
}).
person MichaelLo    schedule 03.04.2014
comment
отлично !, у вас есть пример, где может быть полезно объединение? - person geoom; 22.05.2014
comment
Идея состоит в том, что подход then более полезен, поскольку вы можете проще писать асинхронные операции одну за другой. - person MichaelLo; 22.05.2014

Официальное уведомление: успешное выполнение и ошибка устарели, используйте вместо этого стандартный метод then.

Уведомление об устаревании: Успех и ошибка устаревших методов обещания $ http устарели. Вместо этого используйте стандартный метод then. Если для $ httpProvider.useLegacyPromiseExtensions установлено значение false, эти методы будут вызывать ошибку $ http / legacy.

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

снимок экрана: просмотреть снимок экрана

person MagicBoy    schedule 24.08.2016