AngularJS promise chain
Asked Answered
P

2

5

I have my application that should open a popup ask a confirmation at the user, then make an ajax cal and close the popup.
I tried to do it using a chain of promise (I've already used it, and I remember that it should work in this way), but it seems to block after the call toreservationService.confirm($scope.object);. Now it is a fake service implemented with a setTimeout and $q just to return a promise (in future it will make the ajax call). Is this a valid code or I didn't undestood how promise works?
For the popup I choose AngularUI and the code is this:

 reservationService.book($scope.object, day)
        .then(function(){
            var dialogOpts = {/* dialog options omitted*/}
            return $dialog.dialog(dialogOpts).open();

        })
        .then(function(result){
            console.log('confirmed? ', result);
            if (result){
                //After this line it doesn't do nothing, also if the promise is resolved 
                return reservationService.confirm($scope.object);
            }
        })
        .then(function(){
            //this function is never executed
            $scope.$emit('object:detail',{object: $scope.object});
        });

reservationService:

function confirm(){
     var deferred = $q.defer();
     setTimeout(function(){
          console.log('Confirming');
          deferred.resolve(true)
     }, 500);
     return deferred.promise;
}

SOLVED change setTimeout with $timeout angular's service

Pastime answered 28/8, 2013 at 10:10 Comment(0)
P
6

Used $timeout instead of setTimeout 'cause it works togheter at the angular scope, forcing the digest phase (or use $scope.apply() inside the setTimeout).

Pastime answered 3/9, 2013 at 13:38 Comment(0)
E
2

Can you try

//skipping the first then
.then(function(result){
            var deferred = $q.defer();
            console.log('confirmed? ', result);
            if (result){
                //After this line it doesn't do nothing, also if the promise is resolved 
                return deferred.resolve(reservationService.confirm($scope.object));
            }
            deferred.resolve();
            return deferred.promise;
        })
.then(function(){
                //this function is never executed
                $scope.$emit('object:detail',{object: $scope.object});
            });

For chaining then, the last then success or failure function should return a promise. As the $q documentation mentions

then(successCallback, errorCallback) – regardless of when the promise was or will be resolved or rejected, then calls one of the success or error callbacks asynchronously as soon as the result is available. The callbacks are called with a single argument: the result or rejection reason.

This method returns a new promise which is resolved or rejected via the return value of the successCallback or errorCallback.

Erida answered 28/8, 2013 at 10:25 Comment(5)
In this way it works, but it is at the same way the reservationService works...Pastime
I don't get what you mean to say?Erida
I was editing the post...look now there is the implementation of the confirm method. It is implemented at the same way you did...but why I have to call the deferred.resolve passing in it the promise returned from the service, when it is resolve from the setTimeout?Pastime
reservationService returns a promise so you can call then on it. This then again returns a promise that is resolved by return $dialog.dialog(dialogOpts).open(); (internally i think) hence the next chained then gets called. The second then does return promise but there is no call to resolve it, and hence the next then never gets executed.Erida
ahah no..the problem was something with the setTimeout that doesn't call some phase of angular, in fact, now I changed the setTimeout with $timeout and it works correctly, with my code. Promise then method should return a promise and doesn't have to resolve it.Pastime

© 2022 - 2024 — McMap. All rights reserved.