如何在 angular 循环中使用异步调用? [英] How to use asynchronous calls in a loop in angular?

查看:27
本文介绍了如何在 angular 循环中使用异步调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Each email in a list is to be sent to server and response to be be got from server that if it is a valid email.

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

So after all emails are checked the array should have :

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

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

The code to send the emails to server in a loop is like :

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 不会增加,但事实并非如此.

But the problem is that the calls are asynchronous, so for say i=0, the control will not go inside the function when i is 0. So when it does go inside the function value of i can be anything, mostly it is greater than length of array, so isEmailValidList[i] is undefined. If the call were synchronous then it would have waited for response and i would not have been incremented, but this is not the case.

那么,如何为其相应的电子邮件获得正确的 isValid 响应?

So, how do I get the correct isValid response for its corresponding email ?

推荐答案

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

Use promises. Angular can work with promises without any "special intervention", just like assigning a value to a scope variable, see the plnkr. Promises are the "base" to tame asynchronous programming to work like synchronous programming (while we don't have javascript generators in browsers) and is encouraged by Angular team because it's highly testable and maintainable

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 数组传递给验证服务,然后返回该数组,而不是创建一个中间一系列的承诺.使用angular,你可以为promise分配一个作用域变量,你可以在ng-repeat上使用它而无需对代码进行任何更改

Notes: The $timeout is to emulate an asynchronous task, like a database call, etc. You could pass the entire emails array to the validation service then return the array, instead of creating an intermediate array of promises. With angular, you may assign a scope variable to a promise, and you can use it on ng-repeat without any changes to the code

这篇关于如何在 angular 循环中使用异步调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆