Infinite loop when trying to make Angularjs displa

2019-09-07 06:56发布

问题:

I'm facing an infinite loop when trying to make AngularJS display a promise, as explained in this article: http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/.

I first call $parseProvider.unwrapPromises(true);:

.config(["$parseProvider",
function($parseProvider) {
    $parseProvider.unwrapPromises(true);
}])

Here is the factory I use to access a message:

app.factory("MessageHelper", [
function() {

    // omitted for brevity:
    // calling the server for getting the messages

    return {

        get: function(code) {
            var args = Array.prototype.slice.call(arguments);
            args.shift();
            if (messages) {
                return $q.when(format(messages[code], args));
            }
            var deferred = $q.defer();
            deferredMessages.push({ code: code, args: args, deferred: deferred });
            return deferred.promise;
        }

    };

}]);

Then, in a controller:

$scope.msg = {
    get: function() {
        return MessageHelper.get.apply(this, arguments);
    }
};

Finally, in a view:

<span>{{msg.get("existing.message.code", "first param", "second param")}}</span>

And here is the infinite loop: $scope.msg.get gets called infinitely... Any idea why?

回答1:

You can't have anything with a side effect to scope in any angular expressions, otherwise the infinite loop will occurred.

It's by design to rerun all the expressions repeatedly until nothing has changed. So at the time the promise is resolved, the expressions will get evaluated again.

To avoid that, you could move the msg.get call into the controller and store the promise as an another property in $scope:

$scope.msg = {
    get: function() {
        return MessageHelper.get.apply(this, arguments);
    }
};

$scope.resultMsg = $scope.msg.get("existing.message.code", "first param", "second param");

and use that in the template instead:

{{resultMsg}}

Hope this helps.