Angular $ qpromiseが解決されたかどうかを確認する方法


84

通常、then()promiseを使用する場合は、呼び出しとチェーンの動作を伴う継続コードを添付するだけであることを理解しています。

ただし、プロミスでラップされた非同期呼び出しを開始してから、3秒を個別に開始して$timeout()、元のプロミスがまだ完了していない場合にのみUIアクションを実行できるようにします。(これは、低速接続、3G上のモバイルデバイスなどでのみ発生すると予想されます)

約束が与えられたら、ブロックしたり待ったりせずに、それが完了したかどうかを確認できますか?


2
私はこれに関する問題をangularで開き、役立つ応答を得ましたgithub.com/angular/angular.js/issues/8307#issuecomment-49903373
derekdreery 2014

回答:


46

これはAngularの最近のバージョンで追加されたと思いますが、promiseには$$ stateオブジェクトがあるようです。

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

コメントに記載されているように、Angularバージョンをアップグレードするときに破損する可能性があるため、これはお勧めしません。


25
Angularのドキュメントには、$$...プロパティは使用すべきではないと書かれています。...角の新しいバージョンにアップグレードするときは危険かもしれない
hgoebl

7
あまりにも悪いAngularは、銀の大皿にそのプライベート変数を提供します。:(
ジャクソン


2
しかし、しかし... Angularはinspect関数を実装していませんでした。したがって、Angular開発者にとってはジュースはありません。Promiseプロトタイプにはそれがありません。
Robert Koritnik 2016

36

(Angularソースを変更してプルリクエストを送信せずに)そのままで最善のオプションは、promiseが解決されたかどうかのローカルフラグを保持することだと思います。関心のあるプロミスを設定するたびにリセットthen()し、元のプロミスので完了としてマークします。で$timeout then()、元の約束はまだ解決したりしていない場合は、チェックフラグが知っています。

このようなもの:

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

Kris Kowalの実装には、約束の状態をチェックするための他の方法が含まれ$qていますが、残念ながらAngularの実装にはこれらが含まれていないようです。


9
ここでは.finally()を使用することをお勧めします。上記のコードは、promiseCompletedフラグが正常に解決された場合にのみtrueにマークします。
Karanvir Kang 2016

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にアップグレードするとどうなるかは誰にもわかりません:-/ $q1.2のドキュメントに改善点についての言及はありませんが、おそらく誰かがQに近いより優れた機能セットを備えた代替サービスを作成するでしょう。


ありがとう、しかし「プライベート」メンバーを使用するよりも良いオプションがあります。
ジャクソン

0

正確なシナリオはわかりませんが、非同期呼び出しを行った(そしてpromiseを生成した)直後にタイムアウトを設定するのが一般的です。

提供setTimeout()の文は、非同期呼び出しと同じイベントスレッドである、あなたはレースの影響の可能性について心配する必要はありません。javascriptは厳密にシングルスレッドであるため、promiseの.then()コールバックは後のイベントスレッドで発生することが保証されています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.