2016-05-25 8 views
1

角度の$qとJavascriptのpromise apiを正しく使用することができません。それではまた、私はJavascriptでかなり新しく、構文エラーを起こしている可能性があります。

This質問は似ているようだが、それは正確なコピーではないようです...

私のサービスは、この(私のコントローラによって呼び出される)のような方法があります。

self.getResources = function() { 

    let promises = []; 

    for (let resourceName in $rootScope.resourceNameList) { 

     promises.push($http({ 
      url : '/' + resourceName, 
      method : 'GET' 
     }).then(function (res) { 
      return { resourceName : res.data}; 
     })); 
    } 
    return promises; 
}; 

そして、私をコントローラは、角度の$q.all()に戻す約束のリストを渡します。

let promises = resourceService.getResources(); 

$q.all(promises).then(function (resultsArray) { 

    // resultsArray should be an array of elements like: 
    // [ {cars : [...]}, {coffeePots : [...]}, {motorBoats : [...]} ] 
    // with size = resourceNameList.length(), correct? 

    // this log is never called. 
    console.log(resultsArray); 
    $scope.resources = resultsArray; 
}); 

最後に、私のHTMLに、私はリソースを反復処理して表示しよう:

. 
. 
. 
<!-- 'cars' is and example, but I am trying to retrieve this data in the same way --> 
<tr ng-repeat="item in resources[cars]"> 
    <td>{{item.property1}}</td> 
    <td>{{item.property2}}</td> 
</tr> 

表には結果が表示されません。

コンソールからHTTPリクエストが成功し、データが返ってきていることがわかります。したがって、私はpromiseまたは$q apisで間違いを犯しているはずです。

提案がありますか?

ありがとうございました。あなたはこの

self.getResources = function($q,$http) { 

let promises = []; 

for (let resourceName in $rootScope.resourceNameList) { 

    promises.push($http({ 
     url : '/' + resourceName, 
     method : 'GET' 
    }).then(function (res) { 
     return { resourceName : res.data}; 
    })); 
} 
return promises; 

}のようなディレクティブで$ qと$ HTTPを注入する必要が

+0

あなたはどんな漁獲もしていないので、上流のエラーを飲み込むこともできます。 –

+1

サービスメソッドでは 'resourceName 'プロパティを持つオブジェクトを返しますが、コントローラではそれを考慮していません。 'resourcesArray'をコンソールに記録し、構造体を検査します。あなたはそれをすべて1つの配列にするためにもっと操作する必要があります – charlietfl

+0

は$ q.allを解決しますか?例えばそのブロックにconsole.logを入れて、それが呼び出されているのを見て、resultsArrayは次のように見えますか? – dewd

答えて

2

入力データセットに実際に間違いがあると考えているのでこれはおそらく無回答ですが、実際にはこれらの種類の問題を実際に検出する必要があります。.catchを(少なくとも)あなたの根の約束は、実際に何が起きているかすぐに見ることができます。

あなたのケースでは、これはあなたの根強い約束です(既にキャッチされています)。 私はわかりやすくするために改行にそれを壊れました:

let promises = resourceService.getResources(); 

$q 
.all(promises) 

// unfortunately, .then only gets executed if all of these promises succeed. 
.then(function (resultsArray) { 
    console.log(resultsArray); 
    $scope.resources = resultsArray; 
}) 

// there is a disturbance in the force! 
.catch(function (error) { 
    // you can console.log(error) OR 
    window.open("https://stackoverflow.com/search?q="+error.message); 
}) 
; 

EDIT:あなたは、$q.allに失敗した約束をフィルタリングする必要がある場合だけ$q.allSettledと交換してください!ここでは完全なAPI:共有するhttps://github.com/kriskowal/q

いくつかの追加の考え:すぐに十分な、あなた自身が.allなどで.push.mapを組み合わせたようないくつかの機能が欠けていると$qを訴えています。すでにそのための図書館があります。 BluebirdJSを使用することができます!角度はhere's a nifty wrapper for itです。代わりに、あなたのコードは次のようになります:

Promise.map($rootScope.resourceNameList, function(resourceName) { 
     return $http({ 
     url : '/' + resourceName, 
     method : 'GET' 
     }); 
}, {concurrency: 3}) // did I mention you could control concurrency? 
.then(function(results) { 
    console.log(results); // $http promises that were resolved! 
},function(rejects) { 
    console.log(rejects); // $http promises that were rejected :(
}) 
.catch(function (error) { 
    // you can console.log(error) OR 
    window.open("https://stackoverflow.com/search?q="+error.message); 
}) 
; 

もっと良いでしょうか?

ハッピーコーディング!約束についての素晴らしい記事です:http://taoofcode.net/promise-anti-patterns/

+1

と 'promise'd:' deferred.resolve() 'の1つ: – dewd

+0

' $ q.all() 'の失敗機能を変更する方法があるのか​​どうか分かりませんか?あるいは、少なくとも私が記述した方法で一連の '$ http'呼び出しを実行する別の方法を知っていますが、"落とした "要求は無視していますか?両方の助けをあなたのおかげで今までのところ – Mac

+1

うん、それは 'q.allSettled'です。完全なAPIはhttps://github.com/kriskowal/qです(角度リポジトリの 'package.json'には依存関係として 'q'が付いていますが、これはこのリポジトリを正確に指しています)。 –

0

+0

@OPを過小評価する:)ただ冗談。 –

関連する問題