Search code examples
angularjspromiseangular-promiseangular-resource

What is the difference between $promise and $q promises in angular1.x?


I started using promises in angular for resolving my api calls with the following syntax:

 $scope.module = moduleFactory.get({id: $stateParams.id})
    .$promise.then(function(response){
        $scope.module = response;
     }

Now, I have encountered a situation where I have to chain multiple promises in a for loop and execute some code once all the promises in the for loop have been resolved. I have been trying to search for how to do this with the $promise syntax, but most sources on the internet talk about $q. I am new into development work and am finding it very confusing to juggle between these two concepts ($q and $promise). Request you nice folks to: first, explain to me the difference between $promise and $q; second, if I decide to use $q for solving my present problem as described above, does it mean I will have to rewrite the code that used $promise in order to make it chainable with something like $q.all()?


Solution

  • You can construct a promise in angular by calling $q:

     let promise = $q(function(resolve, reject) { ... };
    

    or if you simply want a promise that resolves immediately:

     let promise = $q.resolve(somevalue);
    

    There is also an older way using $q.defer() to construct a deferred object and returning it's .promise attribute, but you should probably avoid doing it that way and consider it just for backward compatibility.

    The final way to create a new promise is to call .then() (or .catch()) on an existing promise.

    The .$promise attribute is simply a promise created by one of the above mechanisms either by the $resource service or by something following the same pattern.

    Once you have some promises you can stuff them all into an array and use $q.all() to wait for them all to complete, or for one to reject. Or if you want things to happen sequentially you can chain them together by performing each step in the .then() of the previous promise:

     let promise = $q.resolve();
     for(... something ...) {
         promise = promise.then(() => { ... next step here ...});
     }
     promise.then(() => { ... runs when everything completed ...});
    

    That will execute everything in sequence whereas $q.all() starts them off in parallel. Sometimes you want one, sometimes the other:

     let promises = [];
     for(... something ...) {
         promises.push(somethingThatReturnsAPromise());
     }
     $q.all(promises).then(() => { ... runs when everything completed ...});