3

私のアプリケーションには、多数の同期および非同期 ($http 呼び出しを行う) メソッドがあります。コントローラーには、次のようなコードがあります。

$q.all([
    asyncMethod1(),
    syncMethod1()
])
.then(function (results) {

syncMethod1() を待機する必要はありませんが、これを $q.all 内に配置して、物事をシンプルに保ち、将来必要に応じてメソッドを async に変更できるようにします。

同期関数については、次のように呼び出しています。

var syncMethod1 = function () {
    var defer = $q.defer();
    var abc = 99;
    defer.resolve({
        data1: abc,
        data2: 123
    });
    return defer.promise;
};

私が知りたいのは、sync メソッドを $q.all データに戻す方法があるかどうかですが、defer 変数を作成してから defer.promise を返す必要はありませんか? 同期方法をできるだけシンプルにしようとしています。

4

3 に答える 3

1

TL;DR :はい、同期メソッドから通常の値を返し、それら$q.allを入力パラメーターとして使用します。それらを正しく処理します。

長い答え

angular コード$q.allを調べると、この行で入力パラメーターがどのように処理されるかがわかります。

 function all(promises) {
     ....
     forEach(promises, function(promise, key) {
         ....
          ref(promise).then(function(value) {

したがって、各パラメーターは、この行で定義されrefた関数に渡されます。引数を取り、それがプロミスの場合はそれを返しますref

 if (value && isFunction(value.then)) return value;

そうでない場合、値は新しく作成されたプロミスでラップされ、返されます。その約束はできるだけ早く解決されますが、このイベントループの反復では解決されません。

return {
  then: function(callback) {
    var result = defer();
    nextTick(function() {
      result.resolve(callback(value));
    });
    return result.promise;
  }
};

これは、同期メソッドから約束されていない値を安全に返すことができることを意味します。

function asyncFirst() {
    var def = $q.defer();

    $timeout(function(){
      $scope.first = true;
      def.resolve();
    }, 1000);

    return def.promise;
}

function syncSecond() {
     $scope.second = true;
    return {
        data1: 'abc',
        data2: 123
    };
}

$q.all([
    asyncFirst(),
    syncSecond()
])
.then(function(){
    $scope.all = true;
});

この jsbin の例で実際の動作を確認してください

編集: ユーザー @Bergi は、必要に応じて$q.when ソースで通常の値をプロミスに変換できることを示唆していますが$q.when、関数を使用してref値をプロミスに変換し、次のイベント ループの反復でプロミスを解決します。厳密に言えば、遅延なしで返されるため、メソッド自体は同期です。ただし、結果はすぐに promise にラップされ、次のイベント ループの反復まで使用されません。これは、sync メソッドがそのまま使用されていないことを意味します。少なくとも、ほとんどの人が同期方法を想像するわけではありません。の全体的な結果は$q.all、非同期などの同期メソッドを使用する予定ですが、次の反復で解決されます。この警告を考慮してください。

于 2014-05-21T11:27:53.663 に答える
1

$q.all文書化されていなくても、プロミスだけでなくプレーンな値も取ることができます(自動的に変換されます)。あなたの同期方法はちょうどするべきです

return {
    data1: 99,
    data2: 123
};

これは最も単純なものです (実際の同期コンテキストでも使用できます)。


面倒な deferred を使用せずに、値からプロミスを作成するにはどうすればよいですか?

使用できます$q.when

return $q.when({
    data1: 99,
    data2: 123
});

値がまだ Promise でない場合は、できるだけ早く値で解決される Promise が返されます。これは必然的にコードに非同期性を導入することに注意してくださいsyncMethod

于 2014-05-21T11:09:56.537 に答える