Як перевірити, чи вирішено кутове обіцянку $ q


84

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

Однак я хочу розпочати асинхронний дзвінок із заготівлею обіцянки, а потім окремо розпочати 3 секунди, $timeout()щоб я міг виконати дію інтерфейсу, ТІЛЬКИ, якщо оригінальна обіцянка ще не виконана. (Я передбачаю, що це відбудеться лише при повільних з'єднаннях, мобільних пристроях на 3G тощо)

Давши обіцянку, чи можу я перевірити, чи вона завершена чи ні, не блокуючи чи не чекаючи?


2
Я відкрив проблему з цим в angular
derekdreery

можливо дублікат stackoverflow.com/questions/27039771 / ...
mvermand

Відповіді:


46

Я припускаю, що це було додано в недавній версії Angular, але, схоже, зараз у об'єкті є об'єкт стану $$:

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

Як зазначено в коментарях, це не рекомендується, оскільки це може призвести до поломки під час оновлення вашої версії Angular.


25
Кутові документи говорять, що $$...властивості використовувати не слід. Може бути ризикованим при
переході

7
Шкода, що Angular надає свої приватні змінні на срібному блюді. :(
Джексон,


2
Але але ... Angular не реалізував inspectфункцію. Тож ніякого соку для нас, розробників Angular. Прототип Promise просто не має його.
Robert Koritnik

36

Я думаю, що найкращим варіантом, як є, (без зміни джерела Angular та подання запиту на витяг) є збереження локального прапора, якщо обіцянка була вирішена. Скидайте його кожного разу, коли налаштовуєте обіцянку, яка вас цікавить, і позначайте як завершену в then()оригінальній обіцянці. В$timeout then() перевірки позначте прапорець, щоб дізнатися, чи оригінальна обіцянка ще вирішена чи ні.

Щось на зразок цього:

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

Реалізація Kris Kowal включає інші методи перевірки стану обіцянки, але, схоже, реалізація Angular, на $qжаль, їх не включає.


9
Було б краще використовувати .finally () тут. Наведений вище код позначить прапор promisCompleted лише як true, якщо він був успішно вирішений.
Каранвір Канг

8

Здається, це неможливо, як уже згадував @shaunhusain. Але, можливо, це не потрібно:

// 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);

а може і краще:

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

1

У мене була подібна проблема, коли мені потрібно перевірити, чи повернулась обіцянка. Оскільки $watchфункція AngularJS реєструє зміни під час відтворення сторінки, навіть якщо і нові, і старі значення не визначені, я повинен перевірити, чи є дані, які варто зберігати у моїй зовнішній моделі.

Це, безумовно, хак, але я роблю це:

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

Я знаю, що $$vце внутрішня змінна, яку використовує AngularJS, але вона була досить надійною як показник вирішеної обіцянки для нас. Хто знає, що станеться, коли ми перейдемо до AngularJS 1.2: - / Я не бачу жодної згадки про вдосконалення $qв документації 1.2, але, можливо, хтось напише службу заміни з кращим набором функцій ближче до Q.


Дякую, але є кращі варіанти, ніж використання "приватних" учасників.
Джексон

0

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

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

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