【问题标题】:How to use asynchronous calls in a loop in angular?如何在角度循环中使用异步调用?
【发布时间】:2014-05-04 22:55:32
【问题描述】:

列表中的每封电子邮件都将发送到服务器,如果它是有效的电子邮件,则从服务器获取响应。

所以在检查完所有电子邮件后,数组应该有:

joe@gmail.com - valid
abc@fjkdsl.com - invalid
xyz@yahoo.com - valid
test@nknk.com - invalid

循环发送邮件到服务器的代码如下:

for(var i=0; i < isEmailValidList.length; i++) {
  var isEmailValid = User.validateEmail({email : isEmailValidList[i].email}, function(){
      isEmailValidList[i].isValid = isEmailValid.value;
  });
}

但问题是调用是异步的,所以说 i=0,当 i 为 0 时,控件不会进入函数内部。所以当它进入函数内部时,i 的值可以是任何东西,主要是它大于数组的长度,因此 isEmailValidList[i] 未定义。如果调用是同步的,那么它会等待响应并且 i 不会增加,但事实并非如此。

那么,我如何获得与其对应电子邮件的正确 isValid 响应?

【问题讨论】:

    标签: angularjs asynchronous callback


    【解决方案1】:

    你可以使用闭包函数:

    for (var i=0; i < isEmailValidList.length; i++) {
      var isEmailValid = User.validateEmail({
         email : isEmailValidList[i].email
      }, (function(i) {
         return function() {
             isEmailValidList[i].isValid = isEmailValid.value;
         };
      })(i));
    }
    

    【讨论】:

    • 优秀的解决方案,但缺少一个 }。试图编辑,但不允许我这样做
    【解决方案2】:

    使用承诺。 Angular 可以在没有任何“特殊干预”的情况下使用 Promise,就像为范围变量赋值一样,请参阅 plnkr。 Promise 是驯服异步编程以像同步编程一样工作的“基础”(虽然我们在浏览器中没有 javascript 生成器),并且受到 Angular 团队的鼓励,因为它具有高度的可测试性和可维护性

    http://plnkr.co/edit/8BBS2a1kC24BHBWRYp9W?p=preview

    // trying to emulate your service here
    
    var app = angular.module('app', []);
    
    app.factory('User', function($q, $timeout){
      User = {};
    
      User.validateEmail = function(email){
        var d = $q.defer();
    
        $timeout(function(){
          if (/(yahoo|gmail)/.test(email.email)){
            d.resolve(email); // return the original object, so you can access it's other properties, you could also modify the "email" object to have isValid = true, then resolve it
          } else {
            d.resolve(); // resolve it with an empty result
          }
        }, 1000, false);
    
        return d.promise;
      };
    
      return User;
      });
    
    app.controller('MainCtrl', function(User, $q){
      this.emails = [
        {email: 'joe@gmail.com', name: 'Joe'},
        {email: 'abc@fjkdsl.com', name: 'Abc'},
        {email: 'xyz@yahoo.com', name: 'XYZ'}, 
        {email: 'test@nknk.com', name: 'test'}
      ];
    
      this.isEmailValidList = [];
      var promises = [];
    
      for(var i=0; i < this.emails.length; i++) {
        promises.push(
          User.validateEmail(this.emails[i]) 
        );
      }
    
      $q.all(promises).then(function(emails){ 
        this.isEmailValidList = emails.filter(function(e){ return e; });
      }.bind(this));
    
    });
    

    注意:$timeout 用于模拟异步任务,例如数据库调用等。您可以将整个 emails 数组传递给验证服务,然后返回该数组,而不是创建一个中间的 promise 数组。使用 Angular,您可以将范围变量分配给 Promise,您可以在 ng-repeat 上使用它,而无需对代码进行任何更改

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-29
      • 2021-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多