2014-03-26 36 views
1

列表中的每封電子郵件將被髮送到服務器,並且如果它是有效的電子郵件,則將從服務器獲得該響應。如何在角度循環中使用異步調用?

因此,所有的郵件進行檢查後,數組應具有:

[email protected] - valid 
[email protected] - invalid 
[email protected] - valid 
[email protected] - 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 [我]未定義。如果調用是同步的,那麼它會等待響應,我不會增加,但事實並非如此。

那麼,如何才能獲得其相應的電子郵件正確的isValid迴應?

回答

5

使用的承諾。 Angular可以在沒有任何「特殊干預」的情況下使用promise,就像給scope變量賦值一樣,參見plnkr。承諾是「基地」馴服異步編程像同步編程工作(雖然我們沒有在瀏覽器中的JavaScript發電機),由角團隊鼓勵,因爲它的高度可測試性和可維護性

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: '[email protected]', name: 'Joe'}, 
    {email: '[email protected]', name: 'Abc'}, 
    {email: '[email protected]', name: 'XYZ'}, 
    {email: '[email protected]', 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是模擬一個異步任務,例如數據庫調用等,您可以通過電子郵件整個陣列到驗證服務,然後返回,而不是創建承諾的中間陣列的方向。隨着角度,你可以一個範圍變量分配給一個承諾,你可以使用它在ng-repeat無需更改代碼

+0

這工作得很好,感謝工作示例。 – Anubha

3

您可以使用閉合功能:

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)); 
} 
+0

優秀的解決方案,但是一個}缺少。嘗試編輯,但那樣就不會允許我 –

+0

@JimmyMattsson Editted,感謝 – Engineer