11

AngularJS のプロミスの概念に頭を悩ませることはできません。

私はプロバイダーを持っています:

var packingProvider = angular.module('packingProvider',[]);

packingProvider.provider('packingProvider',function(){
    return{
       $get: function($http){
           return{
              getPackings: function(){
                  $http.post('../sys/core/fetchPacking.php').then(function(promise){
                      var packings = promise.data;
                      return packings;
                  });
              }
           }
       }
   }
});

ご覧のとおり、これはメソッドを提供しgetPackings()、オブジェクトを返します

これをメイン アプリケーションで使用してデータを受信すると、呼び出しが非同期になり、データを「待機」しなければならないという問題が発生します。

var packings = packingProvider.getPackings();

console.log(packings); // undefined

プロセスをメインコントローラーにリファクタリングせずにこれを行うにはどうすればよいですか?

4

3 に答える 3

7

試す

var packingProvider = angular.module('packingProvider',[]);

packingProvider.provider('packingProvider',function(){
    return{
       $get: function($http){
           return{
              getPackings: function(){
                  return $http.post('../sys/core/fetchPacking.php').then(function(response){
                      return response.data; // packings
                  });
              }
           }
       }
   }
});

それで

packingProvider.getPackings().then(function(packings){
    console.log(packings);
});

主なアイデア: getPackings 関数から promise オブジェクトを返す必要があります。呼び出しを同期できるかどうかはわかりませんが、そうすることはほとんど間違いなく良い考えではありません。また、「パッキング」をコントローラーのモデル オブジェクトにして、双方向バインディングに使用する場合は、プロミス オブジェクトを安全に割り当てることができます。Angular は、データが通過するとすぐに解決します。

$scope.packings = packingProvider.getPackings();

アップデート

1.2.0-rc.3 の時点で、promise のアンラップは廃止されました ( https://github.com/angular/angular.js/blob/master/CHANGELOG.md#120-rc3-ferocious-twitch-2013-10-14 ) であるため、上記のコード行では双方向バインディングは発生しません。

于 2013-10-08T14:16:29.090 に答える
7

メソッド内からの戻り値はthen、あなたが考えているときに返されません。それは後で戻ってきます。

このステートメントでは、返される promiseが非同期var packings = packingProvider.getPackings();であるため、戻り値は未定義です。$httpつまり、 への呼び出しが$http.post発生し、完了せず、関数が返されることを意味します。何も返さないJS関数では、未定義が返されます。post呼び出しは後で完了して実行さreturn packings;れ、どこにも返されません。

このgetPackingsメソッドは、おそらく Promise を$http.post直接返す必要があります。そうすれば、このメソッドを使用したいコードはすべてthen、promise を直接呼び出して、必要な方法で値を設定できます。コントローラーでは、その約束をに直接割り当てて$scope、ビューで使用できます。これは、その特定の機能を説明する素晴らしい投稿です: http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/

ちなみに、そこには長々としたサービス宣言があるようです。このようなものに短縮しない理由はありますか?

var module = angular.module('packing', []);

module.service('packing', function($http) {
  return {
    getPackings: function() {
      return $http.post('../sys/core/fetchPacking.php');
    }
  };
});

私はAngularJSに比較的慣れていませんが、そのすべてのタイピングに何の利益も見られません。( =

于 2013-10-08T14:20:03.527 に答える
1

jQuery で Deferreds/Promises を使用する方法を示す利用可能なリソースがたくさんあります。それらを検索してみると、このハードルを乗り越えるのに役立つかもしれません. 確かに、AngularJS の約束は jQuery の約束と同じです。

jQuery promise は次のように使用されます。

var getPackings = function() { return $.get('../sys/core/fetchPacking.php'); };
var packings;
$.when(getPackings()).then(function(data){ packings = data; console.log(packings) });

ただし、jQuery ajax 呼び出しには、一般的な Deferred の .when().then() 関数を置き換える .done、.success などの関数があることに注意してください。

上記の jQuery メソッドでは、データを設定して .then() 関数で出力する必要があることがわかります。これは、非同期プロセスが他の場所で行われることを保証できないためです。したがって、理想的には、次のように .then() 関数で処理を続行する関数を呼び出すことになります。

$.when(myAsyncFunc()).then(myAppCanContinue(dataReturnedByAsyncFunc));

Angular も同じロジックに従います。上記を理解すれば、Angular でこれを実現する方法を理解しやすくなります。また、簡単な例を示したこの記事もチェックしてください: http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/

コードを機能させるには、次のようにする必要があります。

packingProvider.provider('packingProvider',function(){
    return{
       $get: function($http){
           return{
              getPackings: function(){
                  return $http.post('../sys/core/fetchPacking.php');
              }
           }
       }
   }
});
var packings = packingProvider.getPackings();

packings.then(function(data) { console.log(data)});
于 2013-10-08T14:45:39.537 に答える