AngularJS $ q.all并不等待承诺

时间:2016-09-30 18:28:53

标签: angularjs ionic-framework ionic2 q

我正在使用Ionic / AngularJS开发一个简单的应用程序,它应该将联系人保存在手机的通讯录中。 我有一个控制器接收联系信息并在检查其存在后保存。这是代码

.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));
    });
};
});

我想检查地址簿中是否已存在联系人,因此我使用$ cordovaContacts.find()方法使用不同的选项(我想检查电子邮件和2个电话号码)。从文档中,这个方法返回一个promise,所以我认为该部分应该是正确的。

问题是,如果我只用1个电话填充promises数组,它就会被解析,我可以输入$ q.all的 then()回调()(此时第二和第三个警报显然是未定义的),但是如果我尝试将其他2个调用放入承诺(取消注释 push()),我不会能够进入然后()回调,我没有警报。 似乎q.all没有等待所有的承诺,因为如果我取消注释 findContactsBySearchTerm()中的alert(),所有代码都像魅力一样!

我对角度和应用程序开发都很陌生,所以我的代码中可能存在错误。请帮我找到.. 任何建议都值得赞赏,甚至是我脚本的整个逻辑

谢谢!

1 个答案:

答案 0 :(得分:1)

根据Promises API的.all,即使其中一个承诺拒绝,它也会拒绝。这可能就是这里发生的事情。

  

Promise.all失败快速行为

     

如果其中一个元素被拒绝且Promise.all快速失败,则拒绝Promise.all:如果你有四个在超时后解决的promise,一个拒绝立即,则Promise.all立即拒绝。

参考here

如果你想做出相应的承诺,你应该使用Promise链。您可以使用:

$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});