2013-05-03 52 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!");}) 
;