Why is my $ q not getting resolved and working as I think?

I always have problems with $ q

Here is an example when .then

started immediately

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

            var modalInstance = $modal.open({
                template: '<p>this is modal</p><a ng-click="ok()">ok</a>',
                controller: function ($scope, $modalInstance) {
                    $scope.ok = function () {
                        $modalInstance.close();
                    };
                }
            });

            modalInstance.result.then(function () {
                console.log('ok');
                deferred.resolve();
            }, function () {
                console.log('Modal dismissed');
            });

            return deferred.promise;
        }

      

In the other place:

    $scope.service.doit().then(
                $scope.variable = 5
            );

      

http://jsfiddle.net/IngoVals/stqwanhm/

I got this on Fiddle while trying to simulate another similar setup where it didn't work at all. What's going on here?

+3


source to share


2 answers


You are passing the value 5

in then

here:

$scope.service.doit().then(
    $scope.variable = 5
);

      

This code works like this:

  • $scope.variable

    assigned a value 5

  • The result of the assignment expression (which is the assigned value 5

    ) is passed tothen

Both of these things happen right away when you call then

. They don't wait for the promise to be resolved.

Instead, you would like to pass a function in then

and set the function to a variable:

$scope.service.doit().then(function() {
    $scope.variable = 5
});

      



Now you are passing the function. The code in the function does not run until it is called, which will be later when the promise is resolved.

Updated script

The good news and the bad news is that this will be much more concise with ES6, because ES6 introduces bold arrow features:

$scope.service.doit().then(() => $scope.variable = 5);

      

This also creates a function and passes it to then

(on an ES6-enabled engine).

I say that this is both good news and bad news because it is beautiful and concise (good!) And also very easy to miss when you read (bad!). :-)

+1


source


It doesn't fire right away, you just update the scope property outside of the callback. This code:

$scope.service.doit().then(
    $scope.variable = 5
);

      

wrong, it must be

$scope.service.doit().then(function() {
    $scope.variable = 5
});

      



The anothe problem is called the so-called deferred anti-pattern . Avoid creating redundant deferred object:

function doit() {
    return $modal.open({
        template: '<p>this is modal</p><a ng-click="ok()">ok</a>',
        controller: function ($scope, $modalInstance) {
            $scope.ok = function () {
                $modalInstance.close();
            };
        }
    }).result.then(function () {
        console.log('ok');
    }, function () {
        console.log('Modal dismissed');
    });
}

      

Demo: http://jsfiddle.net/stqwanhm/2/

+2


source







All Articles