Кутова HttpPromise: різниця між методами "успіх" / "помилка" та аргументами "тоді"


177

За словами документа AngularJS , заклики $httpповернути такі:

Повертає об'єкт обіцянки зі стандартним методом тоді та двома специфічними методами http: успіх та помилка . Потім метод приймає два аргументи успіху і помилки зворотного виклику , яка буде викликана з об'єктом відповіді. Методи успіху та помилки беруть один аргумент - функцію, яка буде викликана, коли запит буде успішним або відмовляється відповідно. Аргументи, передані цим функціям, - це деструктуроване подання об'єкта відповіді, переданого в тодішній метод.

Окрім того, що responseоб’єкт руйнується в одному випадку, я не знаходжу різниці між

  • зворотні виклики успіху / помилки передаються як аргументи promise.then
  • зворотні виклики передаються як аргументи для promise.success/ promise.errorметодів обіцянки

Чи є? У чому сенс цих двох різних способів передавати, здавалося б, однакові зворотні дзвінки?

Відповіді:


156

NB Ця відповідь фактично невірна; як зазначено в коментарі нижче, успіх () повертає первісну обіцянку. Я не змінюсь; і залиште її для редагування.


Основна відмінність двох полягає в тому, що .then()виклик повертає обіцянку (вирішується зі значенням, поверненим з зворотного виклику), тоді як .success()є більш традиційним способом реєстрації зворотних дзвінків і не повертає обіцянку.

Зворотні виклики на основі обіцянок ( .then()) полегшують ланцюжок обіцянок (здійснюйте дзвінок, інтерпретуйте результати, а потім виконайте інший дзвінок, інтерпретуйте результати, виконайте ще один дзвінок тощо).

.success()Метод є обтічним, зручним методом , коли ви не повинні ланцюгами виклику і не працюють з обіцянкою API (наприклад, при маршрутизації).

Коротко:

  • .then() - повна потужність API для обіцянки, але трохи більше багатослівного
  • .success() - не повертає обіцянки, але ображає трохи більш звичний синтаксис

44
Ще одна велика різниця в тому , що thenзворотні виклики приймають єдиний аргумент - відповідь - в той час як successі errorприймати окремі компоненти реакції як arguments-- data, status, header, і config.
Мішель Тіллі

1
@BrandonTilley абсолютно прав, але автор питання вже зрозумів це, тому я не відчував, що мені потрібно це повторити тут.
pkozlowski.opensource

45
Хоча в документації не сказано так явно, ми можемо зробити висновок, що .success()метод повертає початковий об’єкт $ http обіцянки, оскільки ланцюг $http(...).success(...).error(...)можливий. Якщо, як здається розумним, зворотне $http(...).error(...).success(...)також можливе, тоді .error()також слід повернути початковий об'єкт обіцянки. Відмінна відмінність у .then()тому, що вона повертає нову обіцянку.
Буряк-буряк

2
Вихідний код з angular.js служби $ http:promise.success = function(fn) { promise.then(function(response) { fn(response.data, response.status, response.headers, config); }); return promise; };
Алекс Че

6
Зверніть увагу, що successце застаріло. Від 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.
Сем Барнум

204

Тут вже є кілька хороших відповідей. Але варто приїхати додому різниця пропонованого паралелізму:

  • 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()паралельно

3
Зверніть увагу, що нова відповідь на обіцянку, повернута після thenдосягнення результатів, зникає successі errorметодів зникає. Крім того , для HTTP відповідей про помилки (наприклад , 404) перший thenв http.then(ok, err).then(ok, err)перейдете до errоброблювачу , але такі з них будуть проходити в okобробник. В основному, http.success().error().success().error()це можливо, але $ q обіцянки зовсім інші, оскільки вони все стосуються обіцянки та послідовності обробки конкретно (а не обробки запиту http). Мені було важко зрозуміти це, поки я не придивився уважно.
Джиммонт

1
@jimmont successі errorне є нормальним API обіцянки, вони прив'язуються до зворотного значення $ http ().
event_jr

Дякую @event_jr, це мені зрозуміло, і зателефонував у документи. Що не так зрозуміло (для мене) - це те, як $ q і $ http вирішують різні проблеми, а також повертають нові обіцянки проти передачі того ж самого - як вказувалося у вашій (супер корисній) відповіді.
jimmont

1
Що ви маєте на увазі під паралеллю, оскільки JS однонитковий? Ви маєте на увазі, що наказ про виконання є недетермінованим?
Дерек

2
@Derek другий successбуде виконаний після того, як перший виконаний, але перш ніж будь-яка обіцянка, повернута з нього, буде вирішена, тоді як друга thenбуде чекати. Якщо ви не повертаєте обіцянок, то обидва поводяться однаково.
Тамлін

114

Деякі приклади коду для простого 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
});

Використання success/ error:

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

5
Дякую, але питання стосувалося більше різниці в тому, що ці функції виконують, або про причину того, що вони обидва існують, якщо вони роблять те саме. Різниця в тому, як їх використовувати, зрозуміла з док.
ejoubaud

39
Мені особисто подобаються короткі приклади коду, і ось я їх розмістив тут. Кутові документи іноді пропускають короткі точні приклади.
TheHippo

2
Важливо виділити той факт, що об'єкт відповіді першого суті містить "дані, статус, головну область та конфігурацію" другої суті. Це означає, що об'єкти реагування мають один рівень глибини.
geoom

Чи є якась користь передачі значень відповіді змінним, data,status,header,configніж просто повернення response?
ᴍᴀᴛᴛ ʙᴀᴋᴇʀ

27

.then () є можливим і чекатиме попереднього .then () для вирішення.

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

.success () та .error () просто зручні для простих дзвінків (прості виробники):

$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/


Єдина відповідь, яка показує, як працює «повернення - інша обіцянка»
zjk

17

Тільки для завершення, ось приклад коду із зазначенням відмінностей:

успіх \ помилка:

$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
}).

чудово !, чи є у вас приклад, коли конкатенація може бути корисною?
geoom

4
Ідея полягає в тому, що підхід "тоді" є більш корисним, оскільки ви можете простіше писати асинхронні операції одна за одною.
MichaelLo

2

Офіційне повідомлення: успіх та помилка застаріли, замість цього використовуйте стандартний метод.

Повідомлення про депресацію: Успіх і помилка методів обіцянки $ http застаріли. Використовуйте замість цього стандартний метод. Якщо $ httpProvider.useLegacyPromiseExtensions встановлено на значення false, ці методи призведуть до помилки $ http / legacy.

посилання: https://code.angularjs.org/1.5.7/docs/api/ng/service/$http

скріншот: перегляд скріншота

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.