Fabio
Fabio

Reputation: 21

AngularJS $q.all doesn't wait for promises

I'm developing a simple app with Ionic/AngularJS that should save contacts in the address book of the phone. I have a controller that receive contact infos and save it after the check of its existence. Here is the code

.controller('SyncCtrl', function($scope, $q, $cordovaSQLite, $ionicLoading, $cordovaContacts, PSFactory) {

...

$scope.findContactsBySearchTerm = function (field, search) {
    var opts = {       
        filter : search,
        multiple: true, 
        fields:  [field]
    };
    //alert('searching for: ' + field + " - " + search);

    return $cordovaContacts.find(opts);
}

$scope.addContact = function(order) {
    var promises = new Array();
    promises.push($scope.findContactsBySearchTerm('emails', order.customer_email));
    //promises.push($scope.findContactsBySearchTerm('phoneNumbers', order.customer_phone));
    //promises.push($scope.findContactsBySearchTerm('phoneNumbers', order.customer_phone_mobile));

    $q.all(promises).then(function(response) { 
        alert("0: " + JSON.stringify(response[0]));
        alert("1: " + JSON.stringify(response[1]));
        alert("2: " + JSON.stringify(response[2]));

        ...


    }, function errCb(err){
        alert(JSON.stringify(err));
    });
};
});

I want to check if the contact already exists in the address book, so i use the method $cordovaContacts.find() with different options (i want to check for email and 2 phone numbers). From documentation this method returns a promise, so i think that part should be correct.

The problem is that if i fill the promises array with only 1 call it's resolved and i'm able to enter in the then() callback of $q.all() (at this point the second and third alerts are obviously undefined), but if i try to put in the promises the other 2 calls (uncommenting the push()), i'm not able to enter in then() callback and i have no alerts. It seems that q.all is not waiting all promises, because if i uncomment the alert() in findContactsBySearchTerm() all code works like a charm!

I'm totally new to angular and app-developing, so probably there's something wrong in my code. Please help me to find it.. Any advice is appreciated, even about the whole logic of my script

Thanks!

Upvotes: 1

Views: 663

Answers (1)

nikjohn
nikjohn

Reputation: 21832

According to the .all of the Promises API, it rejects even if one of the promises rejects. This is probably what's happening here.

Promise.all fail-fast behaviour

Promise.all is rejected if one of the elements is rejected and Promise.all fails fast: If you have four promises which resolve after a timeout, and one rejects immediately, then Promise.all rejects immediately.

Reference here

If you want to make consequent promises, you should use Promise chaining instead. You can use:

$scope.findContactsBySearchTerm('emails', order.customer_email)
.then( function(responseOfFirstPromise) {
  // Do something with your data
  if(responseOfFirstPromise.length) { $q.reject(error.emailmatch)}
  return $scope.findContactsBySearchTerm('phone', order.customer_phone})
.then(function(responseOfSecondPromise) {
  // Do something with your data
})
.done(function() { //handle the result - resolve/reject});

Upvotes: 1

Related Questions