35

1.2 にアップグレードした後、サービスから返された promise の動作が異なります... シンプルなサービス myDates:

getDates: function () {
           var deferred = $q.defer();

            $http.get(aGoodURL).
                 success(function (data, status, headers, config) {
                     deferred.resolve(data);  // we get to here fine.
            })......

以前のバージョンでは、コントローラーで次のことができました。

$scope.theDates = myDates.getDates();

getDates から返された promise は、Select 要素に直接バインドできます。これは機能せず、コントローラーのプロミスでコールバックを提供する必要があります。そうしないと、データがバインドされません。

$scope.theDates = matchDates.getDates();
$scope.theDates.then(function (data) {
      $scope.theDates = data;  // this wasn't necessary in the past

ドキュメントはまだ言う:

$q プロミスは、Angular のテンプレート エンジンによって認識されます。つまり、テンプレートでは、スコープにアタッチされたプロミスを結果の値であるかのように扱うことができます。

それら(約束)はAngularの古いバージョンで機能していましたが、1.2 RC3自動バインディングでは、すべての単純なサービスで失敗します....私が間違っている可能性があることについてのアイデア。

4

4 に答える 4

40

あなたが言及したものを含め、1.2.0-rc3には変更があります:

AngularJS 1.2.0-rc3 ferocious -twitchは、$compile と $animate の多くの優先度の高い問題を修正し、1.2 への道を開きます。このリリースでは、場合によってはディレクティブやテンプレートが壊れる可能性がある重要な破壊的変更も導入されています。これらの変更を理解し、必要に応じてコードを移行する方法を学ぶために、必ず変更ログをお読みください。このリリースの詳細については、変更ログを参照してください。

変更ログに説明があります:

$パース:

  • 5dc35b52により、$parse とテンプレートは一般的に、 Promise を自動的にアンラップしなくなりました。$parseProvider.unwrapPromises(true)この機能は廃止されました。どうしても必要な場合は、 APIを介して移行期間中に再度有効にすることができます。
  • b6a37d11により、rc.2で追加された、値が promise である場合に関数からの戻り値をアンラップする機能 (promise アンラップが有効な場合 - 前のポイントを参照) は、一般的な使用パターンを壊したために元に戻されました。
于 2013-10-19T22:58:50.433 に答える
3

いつでも Common angular service を作成し、そこに unwrap メソッドを配置して、古い約束がどのように機能したかを再現することができます。メソッドの例を次に示します。

var shared = angular.module("shared");

shared.service("Common", [
    function () {

        // [Unwrap] will return a value to the scope which is automatially updated. For example,
        //      you can pass the second argument an ng-resource call or promise, and when the result comes back
        //      it will update the first argument. You can also pass a function that returns an ng-resource or
        //      promise and it will extend the first argument to contain a new "load()" method which can make the
        //      call again. The first argument should either be an object (like {}) or an array (like []) based on
        //      the expected return value of the promise.
        // Usage: $scope.reminders = Common.unwrap([], Reminders.query().$promise);
        // Usage: $scope.reminders = Common.unwrap([], Reminders.query());
        // Usage: $scope.reminders = Common.unwrap([], function() { return Reminders.query(); });
        // Usage: $scope.reminders.load();
        this.unwrap = function(result, func) {
            if (!result || !func) return result;

            var then = function(promise) {
                //see if they sent a resource
                if ('$promise' in promise) {
                    promise.$promise.then(update);
                }
                //see if they sent a promise directly
                else if ('then' in promise) {
                    promise.then(update);
                }
            };

            var update = function(data) {
                if ($.isArray(result)) {
                    //clear result list
                    result.length = 0;
                    //populate result list with data
                    $.each(data, function(i, item) {
                        result.push(item);
                    });
                } else {
                    //clear result object
                    for (var prop in result) {
                        if (prop !== 'load') delete result[prop];
                    }
                    //deep populate result object from data
                    $.extend(true, result, data);
                }
            };

            //see if they sent a function that returns a promise, or a promise itself
            if ($.isFunction(func)) {
                // create load event for reuse
                result.load = function() {
                    then(func());
                };
                result.load();
            } else {
                then(func);
            }

            return result;
        };
    }
]);

これは基本的に、古い約束と自動解決の方法で機能します。ただし、2 番目の引数が関数の場合は、値をスコープに再読み込みできる ".load()" メソッドを追加するという追加の利点があります。

angular.module('site').controller("homeController", function(Common) {
    $scope.reminders = Common.unwrap([], Reminders.query().$promise);
    $scope.reminders = Common.unwrap([], Reminders.query());
    $scope.reminders = Common.unwrap([], function() { return Reminders.query(); });
    function refresh() {
        $scope.reminders.load();
    }
});
于 2014-01-28T19:41:24.747 に答える
0

これらはいくつかの良い答えであり、角度をアップグレードしたときに問題を見つけるのに役立ち、約束の自動アンラップが機能しなくなりました。

Peter Kriens と冗長になる危険を冒して、私はこのパターンがうまく機能することを発見しました (これは、多数の有名人の引用をページに単純に配置する単純な例です)。

私のコントローラー:

angular.module('myModuleName').controller('welcomeController',
function ($scope, myDataServiceUsingResourceOrHttp) {

    myDataServiceUsingResourceOrHttp.getQuotes(3).then(function (quotes) { $scope.quotes = quotes; });
}
);

マイページ:

...
<div class="main-content" ng-controller="welcomeController">
...
<div class="widget-main">
    <div class="row" ng-repeat="quote in quotes">
        <div class="col-xs-12">
            <blockquote class="pull-right">
                <p>{{quote.text}}</p>
                <small>{{quote.source}}</small>
            </blockquote>
                </div>
    </div>
</div>
...
于 2014-05-30T16:56:51.547 に答える