Angular HttpPromise: sự khác biệt giữa các phương thức `thành công` /` error` và các đối số của` then`


177

Theo tài liệu của AngularJS , các cuộc gọi để $httptrả về như sau:

Returns một lời hứa đối tượng với các tiêu chuẩn sau đó phương pháp và hai http phương pháp cụ thể: thành cônglỗi . Các sau đó phương pháp nhận hai đối số một thành công và một lỗi callback sẽ được gọi với một đối tượng phản ứng. Các phương thức thành cônglỗi có một đối số duy nhất - một hàm sẽ được gọi khi yêu cầu thành công hoặc thất bại tương ứng. Các đối số được truyền vào các hàm này là biểu diễn bị phá hủy của đối tượng phản hồi được truyền vào phương thức then.

Ngoài thực tế là responseđối tượng bị phá hủy trong một trường hợp, tôi không nhận được sự khác biệt giữa

  • các cuộc gọi lại thành công / lỗi được chuyển qua làm đối số của promise.then
  • các cuộc gọi lại được chuyển qua làm đối số cho promise.success/ promise.errorphương thức của lời hứa

Có cái nào không? Điểm của hai cách khác nhau để vượt qua các cuộc gọi lại dường như giống hệt nhau là gì?

Câu trả lời:


156

NB Câu trả lời này thực tế không chính xác; như được chỉ ra bởi một bình luận dưới đây, thành công () không trả lại lời hứa ban đầu. Tôi sẽ không thay đổi; và để nó cho OP chỉnh sửa.


Sự khác biệt chính giữa 2 là .then()cuộc gọi trả về một lời hứa (được giải quyết bằng giá trị được trả về từ cuộc gọi lại) trong khi .success()cách đăng ký gọi lại truyền thống hơn và không trả lại lời hứa.

Các cuộc gọi lại dựa trên Promise ( .then()) giúp dễ dàng xâu chuỗi các lời hứa (thực hiện cuộc gọi, giải thích kết quả và sau đó thực hiện một cuộc gọi khác, giải thích kết quả, thực hiện cuộc gọi khác, v.v.).

Các .success()phương pháp là một phương pháp thuận tiện sắp xếp hợp lý khi bạn không cần phải gọi chuỗi cũng không làm việc với các API lời hứa (ví dụ, trong định tuyến).

Nói ngắn gọn:

  • .then() - toàn bộ sức mạnh của API hứa hẹn nhưng dài dòng hơn một chút
  • .success() - không trả lại lời hứa nhưng cung cấp cú pháp thuận tiện hơn một chút

44
Một sự khác biệt lớn là các thencallbacks mất một đối số duy nhất - phản ứng - trong khi successerrorlấy thành phần riêng lẻ của phản ứng như arguments-- data, status, header, và config.
Michelle Tilley

1
@BrandonTilley hoàn toàn đúng, nhưng tác giả của câu hỏi đã tìm ra nó rồi nên tôi không cảm thấy mình cần phải lặp lại ở đây.
pkozlowski.opensource

45
Mặc dù tài liệu không nói rõ ràng như vậy, chúng ta có thể suy ra rằng .success()phương thức trả về đối tượng lời hứa $ http ban đầu, vì chuỗi $http(...).success(...).error(...)này là có thể. Nếu, như có vẻ hợp lý, điều ngược lại $http(...).error(...).success(...)cũng có thể, thì .error()cũng nên trả về đối tượng lời hứa ban đầu. Sự khác biệt của .then()nó là nó trả lại một lời hứa mới .
Củ cải đường-Củ cải đường

2
Mã nguồn từ angular.js của dịch vụ $ http: promise.success = function(fn) { promise.then(function(response) { fn(response.data, response.status, response.headers, config); }); return promise; };
Alex Che

6
Xin lưu ý rằng successđã được phản đối. Từ 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

Có một số câu trả lời tốt ở đây rồi. Nhưng thật đáng để lái xe về nhà, sự khác biệt trong song song được cung cấp:

  • success() trả lại lời hứa ban đầu
  • then() trả lại một lời hứa mới

Sự khác biệt là then()thúc đẩy các hoạt động tuần tự, vì mỗi cuộc gọi trả lại một lời hứa mới.

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

success() điều khiển các hoạt động song song, vì các trình xử lý được kết nối theo cùng một lời hứa.

$http(/*...*/).
  success(function parFunc1(data){/*...*/}).
  success(function parFunc2(data){/*...*/})
  1. $http.get()
  2. parFunc1(), parFunc2()song song

3
Lưu ý rằng phản hồi lời hứa mới được trả về sau khi thenđạt được kết quả successerrorcác phương thức biến mất. Ngoài ra, đối http báo xử lý lỗi (ví dụ 404) là người đầu tiên thentrong http.then(ok, err).then(ok, err)sẽ được chuyển cho errxử lý nhưng những người sau đây sẽ đi vào okxử lý. Về cơ bản http.success().error().success().error()là có thể kết nối được nhưng các lời hứa $ q hoàn toàn khác nhau ở chỗ chúng hoàn toàn nói về lời hứa và trình tự xử lý cụ thể (và không phải xử lý yêu cầu http). Tôi đã có một thời gian khó hiểu điều này cho đến khi tôi xem xét kỹ.
jimmont

1
@jimmont successerrorkhông phải là API thông thường của một lời hứa, chúng được chốt vào giá trị trả về của $ http ().
event_jr

Cảm ơn @event_jr điều này rõ ràng với tôi và được gọi ra trong các tài liệu. Điều không rõ ràng (với tôi) là cách $ q và $ http giải quyết các vấn đề khác nhau cũng như trả lại những lời hứa mới so với việc vượt qua cùng một vấn đề - như đã chỉ ra trong câu trả lời (siêu hữu ích) của bạn.
jimmont

1
Bạn có ý nghĩa gì khi song song, vì JS là đơn luồng? Bạn có nghĩa là thứ tự thực hiện là không xác định?
Derek

2
@Derek cái thứ hai successsẽ thực thi sau khi cái thứ nhất đã thực hiện nhưng trước khi bất kỳ lời hứa nào được trả lại từ nó được giải quyết trong khi cái thứ hai thensẽ đợi. Nếu bạn không trả lại lời hứa thì cả hai đều cư xử như nhau.
Tamlyn

114

Một số ví dụ mã cho yêu cầu GET đơn giản. Có lẽ điều này giúp hiểu được sự khác biệt. Sử dụng 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
});

Sử dụng success/ error:

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

5
Cảm ơn bạn, nhưng câu hỏi là nhiều hơn về sự khác biệt trong những chức năng này làm gì hoặc lý do tại sao cả hai tồn tại nếu chúng làm điều tương tự. Sự khác biệt trong cách sử dụng chúng là dễ hiểu từ tài liệu.
ejoubaud

39
Cá nhân tôi thích các ví dụ mã ngắn, và đó là tôi đã đăng chúng ở đây. Các tài liệu Angular đôi khi bỏ lỡ các ví dụ chính xác ngắn.
TheHippo

2
Điều quan trọng là làm nổi bật thực tế là đối tượng phản hồi của ý chính thứ nhất chứa "dữ liệu, trạng thái, tiêu đề và cấu hình" của ý chính thứ hai. Điều đó có nghĩa là các đối tượng trả lời có một cấp độ sâu.
geoom

Có bất kỳ lợi ích nào của việc chuyển các giá trị phản hồi cho các biến data,status,header,configchỉ đơn giản là trả về responsekhông?
ᴍᴀᴛᴛ 24/11/2015

27

.then () có thể kết nối được và sẽ đợi .then () trước đó giải quyết.

.success () và .error () có thể bị xiềng xích, nhưng tất cả chúng sẽ bắn cùng một lúc (vì vậy không có nhiều điểm cho điều đó)

.success () và .error () chỉ tốt cho các cuộc gọi đơn giản (nhà sản xuất dễ dàng):

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

vì vậy bạn không cần phải gõ cái này:

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

Nhưng nói chung tôi xử lý tất cả các lỗi với .catch ():

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

Nếu bạn cần hỗ trợ <= IE8 thì hãy viết .catch () và .finally () như thế này (các phương thức dành riêng trong IE):

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

Ví dụ làm việc:

Đây là một cái gì đó tôi đã viết ở định dạng nhiều mã hơn để làm mới bộ nhớ của mình về cách tất cả diễn ra với các lỗi xử lý, v.v.

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


Câu trả lời duy nhất cho thấy "lời hứa trở lại khác" hoạt động như thế nào
zjk

17

Chỉ cần hoàn thành, đây là một ví dụ mã cho thấy sự khác biệt:

thành công \ lỗi:

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

sau đó:

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

tuyệt vời!, bạn có một ví dụ mà việc ghép có thể hữu ích không?
geoom

4
Ý tưởng là cách tiếp cận "sau đó" hữu ích hơn, vì bạn có thể dễ dàng viết các thao tác không đồng bộ lần lượt từng bước một.
MichaelLo

2

Thông báo chính thức: thành công và lỗi đã không được chấp nhận, vui lòng sử dụng phương pháp tiêu chuẩn sau đó thay thế.

Thông báo khấu hao: Các phương pháp hứa hẹn di sản $ http thành công và lỗi đã bị phản đối. Sử dụng tiêu chuẩn sau đó phương pháp thay thế. Nếu $ httpProvider.useLegacyPromiseExtensions được đặt thành false thì các phương thức này sẽ đưa ra lỗi $ http / legacy.

liên kết: https://code.angularjs.org/1.5.7/docs/api/ng/service/$http

ảnh chụp màn hình: xem ảnh chụp màn hình

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.