Angular JS – Defer, Promise and Resolve + Minification

There are cases in which is not sufficient to rely on the Angular functions to perform the necessary operation within a controller. In these cases, if the operations are asynchronous, will be necessary to wait for their completion before to be able to add their result to the $scope object.

The problem is that outside the Angular’s functions (such as the $http.get(), that is asynchronous, but is managed by Angular to work properly) there are issues when you try to assign something on the $scope object from an asynchronous function’s callback.

In these cases is possible to use the premises mechanism, that is accessible from Angular by adding the $q parameter. A premise allow you to assign a certain code block (defined inside the then() method) to the time in which a particular data becomes available. The data’s availability is notified through the resolve() method, that triggers the execution of the then() method with the data’s value passed as parameter.

Here is an example of how you could make the binding work if you decide to not use the $http.get() to read a remote json, but a normal jQuery ajax call (note that without the premises mechanism it would not work):

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Angular JS</title>
</head>
<body>
    <div data-ng-app="myApp" data-ng-controller="myController">
 
        <!--
            I can use premises to defer the assignation of an
            element to when an asynchronous operation has finished
            -->
        <h3>Deferred</h3>
        <ul>
            <li data-ng-repeat="place in places">
                <p>The place is: {{ place.Name + ', ' + place.Country }}</p>
            </li>
        </ul>
        <hr />
    </div>
 
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
 
    <script>
        var app = angular.module("myApp", []);
 
        app.controller("myController", ["$scope", "$q", function myController($scope, $q) {
            var page = "/JS/Feeds/testFeed.js";
 
            var d = $q.defer();
            d.promise.then(function (p) {
                $scope.places = p;
            });
 
            $.ajax({
                dataType: "json",
                url: page,
                success: function (response) {
 
                    //Add the response to the model
                    d.resolve(response);
                }
            });
        }]);
    </script>
</body>
</html>

Minification handling

You can note that this time the controller is defined within an array and is preceded by the parameters’ names expressed as strings. This is useful because for Angular the parameters’ names are important, not just the positions (for example in this case the name of the second parameter is $q, but if I had put a different name (such as $http) it would give me a different object). The problem is that the minification process tends to rename them, with the result that the controller is not able to work properly. By writing in this way Angular is still able to understand which parameters we are referring to.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s