Skip to content Skip to sidebar Skip to footer

Can I Use $q.all In AngularJS With A Function That Does Not Return A .promise?

If I have the following functions: doTask1: function ($scope) { var defer = $q.defer(); $http.get('/abc') .success(function (data) { defe

Solution 1:

$q.when is used in scenarios where you don't know upfront whether the function is returning a promise or a direct value.

The following example/plunker shows a method, whose result is used in $q.all, and which returns different type of object (int or promise) every time it's called:

PLUNKER

app.controller('MainController', function($scope, $q, $http) {
  var count = 0;

  function doTask1() {
    var defer = $q.defer();
    $http.get('abc.json')
      .success(function (data) {
        defer.resolve(data);
      })
      .error(function () {
        defer.reject();
      });
       
    return defer.promise;
  }

  /**
   * This method will return different type of object 
   * every time it's called. Just an example of an unknown method result.
   **/
  function doTask2() {
    count++;
    var x = 99;
    if(count % 2){
      console.log('Returning', x);
      return x;
    } else {
      var defer = $q.defer();
      defer.resolve(x);
      console.log('Returning', defer.promise);
      return defer.promise;
    }
    
  }
  
  $scope.fetchData = function(){

    // At this point we don't know if doTask2 is returning 99 or promise.
    // Hence we wrap it in $q.when because $q.all expects 
    // all array members to be promises
    $q.all([
      $q.when(doTask1()),
      $q.when(doTask2())
    ])
      .then(function(results){
        $scope.results = results;
      });
      
  };
  
});
<body ng-app="myApp" ng-controller='MainController'>
  <button ng-click="fetchData()">Run</button>
  <pre>{{results|json}}</pre>
</body>

Solution 2:

is there an easier way to do this [than manually constructing and resolving a deferred and returning a promise]?

Yes, use the $q.when function:

doTask2: function ($scope) {
    return $q.when( 99 );
},

However, you don't actually need to do this. $q.all will - though not stated in the docs - also work with non-promise values (implementation calls _ref which converts it). So just

return 99;

is fine as well. However, if you know beforehand that it's synchronous, using promises doesn't seem to make much sense.


Post a Comment for "Can I Use $q.all In AngularJS With A Function That Does Not Return A .promise?"