2013-05-03 51 views
1

我已經看到很多關於這個問題,但似乎沒有給我的情況正確的答案。 我見過也使用.pipe的答案,但我正在尋找一個使用.then的答案。循環和鏈接使用推遲的Ajax調用

好的。我需要做3個Ajax調用,讓我們說一個允許多個賬戶的投票應用程序。 需要完成以便賬戶可以投票的過程如下。

  1. 登錄
  2. 選擇選項/ s的
  3. 提交
  4. 註銷(只是清除餅乾,沒必要張貼)。

比方說,我有2個賬戶:

var accts = [{user: "acct1", pswd: "1234"},{user: "acct2", pswd: "4321"}]; 

現在我需要通過這些帳戶循環使用jQuery的$.each

$.each(accts, function(key,value){ 

}); 

我瞭解到,使用$.Deferred可以做到這一點很好,但正確的實施。

我要的是

--------loop1-------- 
login 
select 
vote 
--------loop2-------- 
login 
select 
vote 
All Done!. 

但發生的事情是(當我嘗試console.log上正在發生的事情) 全部完成! 登錄(2) 選擇(2) 投票(2)

因此,這裏是我的代碼:

$.each(data, function(k, v) { 
    promise.then(function() { 
     return $.post(loginURL, {user: v.username, passwrd: v.password}); 
    }).then(function(html) { 
     if (data > 0) { 
      console.log('Logged In!'); 
      return $.post(pollURL + 'select.php', {id: 143}); 
     } else { 
      console.log('Login Failed.'); 
      return false; 
     } 
    }).then(function(data) { 
     if (data === 'selected') { 
      console.log('Already have a selection.'); 
      return false; 
     } else { 
      return $.post(pollURL + 'submit.php'); 
     } 
    }).then(function(data){ 
     if(data > 1) { 
      Console.log('Successfully Voted.'); 
     } else { 
      // if possible return to the login? 
     } 
    }); 
}); 

promise.done(function() { 
    console.log('All Done. Logged out.'); 
}); 

我在做什麼錯?

回答

6

啊,這和我一陣掙扎的過程很相似。我的解決方案是在jQuery的.when上使用.apply來處理「未知」數量的ajax調用並解決所有問題。

這並不完全是您根據自己的情況需要的,但它可能會爲您提供一些有關如何解決問題的想法。我試圖說明你正在嘗試做什麼的情況下,我的過程,所以

var ajaxArgs = [{id: 1, password: "qwerty"}, {id: 2, password: "zxcvb"}]; 

function doLogin(id, pass) { 
    return $.post("ws/path/here", {id: id, pass: pass}); 
} 

var logins = $.when.apply(null, ajaxArgs.map(function(argSet) { 
    return doLogin(argSet.id, argSet.password); 
}); 

logins.done(function(){ 
    var logins = [].concat(arguments); 
    logins.forEach(function(login) { 
     //do Vote 
     //do Logout 
    }); 
}); 
+1

'argSet.password'? – 2013-05-03 21:02:37

+1

@甜菜根 - 甜菜根:固定。爲OP寫了所有這些,並沒有意識到我混淆了我的變量/屬性名稱 – BLSully 2013-05-03 21:04:58

1

我將這個有點不同,以簡化它。首先,寫一個函數處理一個用戶,返回一個承諾,在完成處理該用戶:

function one_user(v){ 
    return $.post(loginURL, {user: v.username, passwrd: v.password}) 
    .then(function(data) { 
     if (data <= 0) { throw "Login failed."; } 
     console.log('Logged In!'); 
     return $.post(pollURL + 'select.php', {id: 143}); 
    }) 
    .then(function(data) { 
     if (data === 'selected') {throw 'Already have a selection.';} 
     return $.post(pollURL + 'submit.php'); 
    }) 
    .then(function(data) { 
     if(data > 1) { 
      Console.log('Successfully Voted.'); 
     } else { 
      // if possible return to the login? 
     } 
    }) 
    .fail(function(e) {console.log("Error: "+e);}) 
    ; 
} 

請注意,我已經更換了錯誤處理與fail末一起使用throw,更像承諾一樣處理「錯誤」。

現在,您的頂級序列無非是

$.when( function() {return one_user(user1);}) 
    .then(function() {return one_user(user2);}) 
    .then(function() {console.log("All done!");}; 

請注意,該功能通過時/然後在上面自己返回承諾。在編寫基於promise的代碼時,這是一種常見模式,它允許您將問題分解爲各個承諾序列,然後將這些序列串在一起。

如果您有user_array幾個用戶,雖然不同的承諾框架有稍微不同的方式來處理這個問題,一個簡單的方法是使用reduce,所以:

user_array.reduce(
    function(prev,cur){ 
     prev=prev.then(function(){return one_user(cur);}); 
    }), 
    $.Deferred().resolve() 
) 
.then(function() {console.log("All done!");}) 
;