Cách luôn chạy một số mã khi một lời hứa được thực hiện trong Angular.js


83

Trong ứng dụng Angular.js của tôi, tôi đang chạy một số hoạt động không đồng bộ. Trước khi nó bắt đầu, tôi bao phủ ứng dụng bằng một div phương thức, sau đó khi hoạt động hoàn tất, tôi cần xóa div, cho dù hoạt động có thành công hay không.

Hiện tại tôi có cái này:

LoadingOverlay.start(); 
Auth.initialize().then(function() {
    LoadingOverlay.stop();
}, function() {
    LoadingOverlay.stop(); // Code needs to be duplicated here
})

Nó hoạt động tốt, tuy nhiên tôi muốn có thứ gì đó rõ ràng hơn như mã giả này:

LoadingOverlay.start(); 
Auth.initialize().finally(function() { // *pseudo-code* - some function that is always executed on both failure and success.
    LoadingOverlay.stop();
})

Tôi cho rằng đó là một vấn đề khá phổ biến, vì vậy tôi đã nghĩ rằng nó có thể được thực hiện nhưng không thể tìm thấy gì trong tài liệu. Bất kỳ ý tưởng nếu nó có thể được thực hiện?


Nếu bạn có thể chuỗi một then(), sau đó bạn có thể chắc chắn chuỗi khác ... .initialize().then(...).then(...). Không có "cuối cùng" như vậy; trình xử lý cuối cùng là trình xử lý cuối cùng được chỉ định.
Củ cải đường-Củ cải đường

2
@ Củ cải đường-Củ cải đường, điều đó sẽ không hoạt động vì nếu initialize()thất bại, bạn vẫn cần khai báo cả hàm "thành công" và hàm "thất bại" và mã trùng lặp trong đó.
laurent

Sẽ không hoạt động, hoặc chỉ không phù hợp?
Củ cải đường Củ cải đường-

1
Laurent, những gì bạn muốn hiện không có sẵn trong dịch vụ $ q nhẹ của Angular, cung cấp các lời hứa chỉ với một phương pháp, .then()- hãy xem "API Promise" tại đây . Quyền tự do duy nhất là có một .then()hoặc nhiều chuỗi .then(). Bạn không phải là người đầu tiên mong muốn có một API hứa hẹn mở rộng hơn - tính năng bạn muốn được yêu cầu chính thức tại đây .
Củ cải đường-Củ cải đường

1
Rõ ràng always(callback)là không được thực hiện hoặc cuộn lại trong góc 1.2.6. Chúng ta phải sử dụng finallyngay bây giờ. Tôi tự hỏi tại sao từ dành riêng lại finallytốt hơn always.
Aleyna

Câu trả lời:


164

Tính năng đã được thực hiện trong yêu cầu kéo này và hiện là một phần của AngularJS. Ban đầu nó được gọi là "always" và sau đó được đổi tên thành finally, do đó, mã sẽ như sau:

LoadingOverlay.start(); 
Auth.initialize().then(function() {
    // Success handler
}, function() {
    // Error handler
}).finally(function() {
    // Always execute this on both error and success
});

Lưu ý rằng vì finallylà một từ khóa dành riêng nên có thể cần phải đặt nó thành một chuỗi để nó không bị hỏng trên một số trình duyệt nhất định (chẳng hạn như IE và Trình duyệt Android):

$http.get('/foo')['finally'](doSomething);

10
Đối với bất kỳ ai tìm thấy điều này từ tìm kiếm trên web, liên kết trong câu trả lời đề cập đến hàm alwaysnhưng nó đã được thay đổi thành finallynhư bạn có thể thấy trong cam kết này (hoặc trong nguồn): github.com/angular/angular.js/commit/…
Austin Thompson

@AustinThompson, cảm ơn vì thông tin, tôi đã cập nhật bài đăng.
đoạt giải

@ this.lau_ cuối cùng () có phải là lệnh gọi cuối cùng trong chuỗi không, hay tôi có thể xâu chuỗi thêm sau đó () không?
Brian

2
Ngài đã làm nên ngày của tôi!
JacobF

4
@Brian finallytrả về một lời hứa giống như phần còn lại, vì vậy bạn có thể xâu chuỗi nó. Tuy nhiên (ít nhất là trên một số phiên bản của Angular) sự tiện lợi quá tải successerrorchỉ được thêm vào để trả về ngay lập tức $http, vì vậy nếu bạn bắt đầu với finallybạn, bạn sẽ mất các phương thức đó.
drzaus

7

Tôi đang sử dụng Umbraco phiên bản 7.3.5 back end với AngularJS phiên bản 1.1.5 và tìm thấy chủ đề này. Khi tôi triển khai câu trả lời được chấp thuận, tôi gặp lỗi:

xxx (...). then (...). cuối cùng không phải là một hàm

Tuy nhiên, những gì đã làm việc always. Nếu bất kỳ ai khác sử dụng phiên bản AngularJS cũ tìm thấy chuỗi này và không thể sử finallydụng, hãy sử dụng mã này thay thế

LoadingOverlay.start(); 
Auth.initialize().then(function() {
    // Success handler
}, function() {
    // Error handler
}).always(function() {
    // Always execute this on both error and success
});

2

Đối với những người không sử dụng angleJS và nếu bạn ổn với việc bắt lỗi (không chắc liệu .finally () có làm được điều đó hay không), bạn có thể sử dụng .catch (). Then () để tránh mã trùng lặp.

Promise.resolve()
  .catch(() => {})
  .then(() => console.log('finally'));

Bắt () dù sao cũng có thể hữu ích cho việc ghi nhật ký hoặc các thao tác dọn dẹp khác. https://jsfiddle.net/pointzerotwo/k4rb41a7/


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.