Cách kiểm tra xem lời hứa Angular $ q có được giải quyết hay không


84

Tôi hiểu rằng thông thường người ta sẽ chỉ đính kèm mã tiếp tục với then()hành vi gọi và chuỗi khi sử dụng các lời hứa.

Tuy nhiên, tôi muốn bắt đầu cuộc gọi không đồng bộ được bao bọc bởi lời hứa và sau đó bắt đầu riêng biệt trong 3 giây $timeout()để tôi có thể thực hiện một hành động trên giao diện người dùng, CHỈ KHI lời hứa ban đầu chưa hoàn thành. (Tôi dự đoán rằng điều này sẽ chỉ xảy ra trên các kết nối chậm, thiết bị di động trên 3G, v.v.)

Với một lời hứa, tôi có thể kiểm tra xem nó đã hoàn thành hay chưa mà không cần chặn hoặc chờ đợi?


2
Tôi mở một vấn đề về vấn đề này ở góc và nhận được một câu trả lời hữu ích github.com/angular/angular.js/issues/8307#issuecomment-49903373
derekdreery

có thể trùng lặp của stackoverflow.com/questions/27039771/...
mvermand

Câu trả lời:


46

Tôi đoán điều này đã được thêm vào trong một phiên bản gần đây của Angular nhưng có vẻ như bây giờ có một đối tượng trạng thái $$ trong lời hứa:

 var deferred = $q.defer();
 console.log(deferred.promise.$$state.status); // 0
 deferred.resolve();
 console.log(deferred.promise.$$state.status); //1 

Như đã lưu ý trong các nhận xét, điều này không được khuyến khích vì nó có thể bị hỏng khi nâng cấp phiên bản Angular của bạn.


25
Angular docs nói rằng $$...không nên sử dụng thuộc tính. Có thể là rủi ro khi nâng cấp lên phiên bản mới hơn của góc ...
hgoebl

7
Quá tệ là Angular cung cấp các biến riêng của nó trên một đĩa bạc. :(
Jackson


2
Nhưng ... Angular không thực hiện inspectchức năng. Vì vậy, không có nước trái cây cho chúng tôi Angular devs. Nguyên mẫu Promise đơn giản là không có nó.
Robert Koritnik

36

Tôi nghĩ rằng lựa chọn tốt nhất của bạn hiện tại, (không sửa đổi nguồn Angular và gửi yêu cầu kéo) là giữ cờ cục bộ nếu lời hứa đã được giải quyết. Đặt lại nó mỗi khi bạn thiết lập lời hứa mà bạn quan tâm và đánh dấu nó là hoàn thành then()đối với lời hứa ban đầu. Trong $timeout then()cờ kiểm tra để biết liệu lời hứa ban đầu đã được giải quyết hay chưa.

Một cái gì đó như thế này:

var promiseCompleted = false;
promise.then(function(){promiseCompleted=true;})
$timeout(...).then(function(){if(!promiseCompleted)doStuff()})

Việc triển khai Kris Kowal bao gồm các phương pháp khác để kiểm tra trạng thái của lời hứa nhưng có vẻ như việc triển khai của Angular $qrất tiếc không bao gồm những phương pháp này.


9
Sẽ tốt hơn nếu sử dụng .finally () ở đây. Đoạn mã được cung cấp ở trên sẽ chỉ đánh dấu cờ hứa hẹn là true nếu nó được giải quyết thành công.
Karanvir Kang

8

Điều này dường như không thể thực hiện được như @shaunhusain đã đề cập. Nhưng có lẽ nó không cần thiết:

// shows stuff from 3s ahead to promise completetion, 
// or does and undoes it in one step if promise completes before
$q.all(promise, $timeout(doStuff, 3000)).then(undoStuff);

hoặc có thể tốt hơn:

var tooSlow = $timeout(doStuff, 3000);
promise.always(tooSlow.cancel);

1

Tôi đã gặp vấn đề tương tự, nơi tôi cần kiểm tra xem một lời hứa đã trở lại hay chưa. Vì $watchchức năng của AngularJS sẽ đăng ký thay đổi trong khi hiển thị trang ngay cả khi cả giá trị mới và cũ đều không được xác định, nên tôi phải kiểm tra xem có dữ liệu nào đáng lưu trữ trong mô hình bên ngoài của mình không.

Nó chắc chắn là một hack nhưng tôi làm điều này:

$scope.$watch('userSelection', function() {
  if(promiseObject.hasOwnProperty("$$v"){
    userExportableState.selection = $scope.userSelection;
  }
};

Tôi biết đó $$vlà một biến nội bộ được AngularJS sử dụng, nhưng nó khá đáng tin cậy như một chỉ báo về một lời hứa đã được giải quyết cho chúng tôi. Ai biết được điều gì sẽ xảy ra khi chúng tôi nâng cấp lên AngularJS 1.2: - / Tôi không thấy bất kỳ đề cập nào về những cải tiến $qtrong tài liệu 1.2 nhưng có lẽ ai đó sẽ viết một dịch vụ thay thế với một tính năng tốt hơn gần Q.


Cảm ơn, nhưng có nhiều lựa chọn tốt hơn là sử dụng các thành viên "riêng tư".
Jackson

0

Tôi không biết tình huống chính xác của bạn nhưng điển hình hơn là đặt thời gian chờ ngay sau khi thực hiện cuộc gọi không đồng bộ (và tạo lời hứa).

Cung cấp setTimeout()câu lệnh nằm trong cùng một chuỗi sự kiện với cuộc gọi không đồng bộ, bạn không cần lo lắng về khả năng xảy ra hiệu ứng cuộc đua. Vì javascript hoàn toàn là một luồng, các lệnh .then()gọi lại của lời hứa được đảm bảo sẽ kích hoạt trong một chuỗi sự kiện sau này.

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.