2013-12-13 18 views
16

一連のリモート呼び出しを解決するローカルデータをいくつか書き込もうとしています。
約束がすべて解決されると、私はデータを読み込んで処理を進めます。まさにこれを行い$q.all([])

方法は:

 $q.all([ 
      this.getUserInfo(11) 
       .then(function (r) { 
        results.push(r) 
       }), 

      this.getUserConns() 
       .then(function (r) { 
        results.push(r) 
       }), 

      this.getUserCtxs() 
       .then(function (r) { 
        results.push(r) 
       }) 
     ]) 
     .then(function() { 
      console.log(results) 
     }) 


問題があり、このコードは、弾性ではありません。
これらの呼び出しのいずれかが失敗した場合、誰も魚を取得しません! try/catch文で呼び出しをラップ

、単に...(FUNCではconsole.logに注意してください)失敗していない場合でも、完全にエントリを無視する$q.all()を引き起こし

 $q.all([ 
      this.getUserInfo2(11) 
       .then(function (r) { 
        results.push(r) 
       }), 

      function() { 
       try { 
        this.getUserGroups() 
         .then(function (r) { 
          console.log(r) 
          results.push(r) 
         }) 
       } 
       catch (err) { 
        console.log(err) 
       } 
      }, 
     ]) 
     .then(function() { 
      console.log(results) 
     }) 

出力:

【課題】


私はこれをどのようにして弾力性に富むことができますか?


@dtabuencのおかげで、私はさらに一歩進んできました。 エラーコールバックを実装することで、チェーンの破損を回避し、解決された約束の値をプッシュすることができます。

しかし、コンソールには厄介な例外が表示されています... 非同期要求を試しても捕まえられない場合は、どうすれば取り除くことができますか?

発信者コード

return $q.all([ 

      this.getUserInfo(user_id) 
       .then(function (r) { 
        results['personal_details'] = r 
       }), 

      this.getUserConns() 
       .then(
        function (r) { 
        results['connections'] = r 
        }, 
        function(err) { 
         console.log(err) 
        }) 

     ]) 
     .then(function() { 
      return (results) 
     }) 

呼び出し先コード(例外で注入)

getUserConns: function() { 

     return __doCall(ws.getUserConnections, {}) 
      .then(function(r) { 

       // very generic exception injected 
       throw new Error 

       if (r && r.data['return_code'] === 0) { 
        return r.data['entries'] 
       } 
       else { 
        console.log('unable to retrieve the activity - err: '+r.data['return_code']) 
        return null 
       } 
      }) 
    }, 

答えて

23

これは機能するだけでなく、エラーを配列にプッシュします。

function push(r) { 
    results.push(r); 
} 

$q.all([ 
    this.getUserInfo(11).then(push).catch(push), 
    this.getUserConns().then(push).catch(push), 
    this.getUserCtxs().then(push).catch(push) 
]) 
.then(function() { 
    console.log(results); 
}) 

あなたはまた、約束のご理解を向上させる必要があり、あなたが約束とtry-catchを使うべきではありませんでし - 約束を使用しているとき、あなたは(他のすべて暗黙的にtryである).catch()メソッドを使用します。これは通常のエラーだけでなく非同期エラーでも機能します。


あなたは完全にエラーを無視する場合:ここ

function push(r) { 
    results.push(r); 
} 

function noop() {} 

$q.all([ 
    this.getUserInfo(11).then(push).catch(noop), 
    this.getUserConns().then(push).catch(noop), 
    this.getUserCtxs().then(push).catch(noop) 
]) 
.then(function() { 
    console.log(results); 
}) 
+0

実際、私はAngular、約束、さらにはJSの初心者です。私は毎日新しいことを学ぶことが大変です! .catch()メソッドは、私の最後の例で私が生成した例外を "ブロック"しませんが、理想的な結果に近づけることができると思います。 ありがとう! – domokun

+1

@domokunアングルプロミスは、プロミス/ A +の精神に反して、キャッチされた例外を誤って報告しています。スペックを違反していない場合は – Esailija

+0

知っておいてください...私はそう思います... Thx again! – domokun

0

私はあなたが弾力性によって何を意味するかわかりません。約束事の1つが失敗した場合、あなたは何をしたいですか?

プロビジョニングが非同期で失敗するため、try-catchが機能しません。

ただし、エラーハンドラをthen()コールの2番目のパラメータとして渡して、何でもできます。

+0

よかった、エラーコールバックを忘れました。 鎖が中断されないという意味で弾力性があり、それが私の望むものです。 しかし、私はそれをキャッチしないと例外を隠すことはできません... 説明するために私の質問を更新します – domokun

+0

私はあなたがHTTPエラーをキャッチすることはできないと思います。それらは常にコンソールに表示されます。これは、角度を使用しているかどうかにかかわらずです。 – dtabuenc

+0

これは本当であり、私を気にしません。 私は実際にコンソールに例外を表示しています。 私の更新された質問を見てください – domokun

0

同じ問題。 レスポンス内側::forループとのあなたのそれらのために

var tracks = []; 
var trackDfds = []; 
for(var i = 0; i < res.items.length; i++){ 
    var fn = function() { 
     var promise = API.tracks(userId, res.items[i].id); 
     return promise.then(function (res) { 
      if (res.items.length) { 
       tracks.push(res.items); 
      } 
     }).catch(angular.noop); 
    }; 
    trackDfds.push(fn()); 
} 
$q.all(trackDfds) 
    .then(function (res) { 
     console.log(tracks); 
    }); 
1

私はそれを行うにはより簡単だと思う:

$q.all([ 
mypromise1.$promise.catch(angular.noop), 
mypromise2.$promise.catch(angular.noop), 
mypromise1.$promise.catch(angular.noop) 
]) 
.then(function success(data) { 
//..... 
}); 
0

Esailijaの答え@問題の回避策のように思えます。 問題の主原因外の問題を解決することはできません:$q

then(第2引数)ごとに拒否コールバックを持ち、そこに$q.reject(...)を挿入する方が少し賢明です。

例:

$q.all([ 
    this.getUserInfo(11).then(
     function (response) { // UI data preparation for this part of the screen }, 
     function (response) { 
      $q.reject(response); 
     } 
    ), 
    // ... 
]) 
.then(
    function() { 
     // all good 
    }, 
    function() { 
     // at least one failed 
    } 
) 

これは、UIモデルは、すべてのAJAX呼び出しに依存する場合に特に示されています。

個人的には、拒否コールバックでいくつかのサーバーメッセージをいくつかのトーストコンポーネントにプッシュしたい場合や、何らかの方法でユーザーに警告する場合が多いため、これは安全な方法です(キューブ7 ajax呼び出し1が失敗したため何も表示できないというわけではありません。つまり、画面の一部の領域を表示できなくなり、ユーザーに特別なフィードバックが必要となります。

関連する問題