2012-08-16 67 views
1

继续我的问题,从另一天开始,我遇到了另一件事情,现在我已经花了太多时间敲打我的头。表单提交与AJAX轮询呼叫

大部分情况下,我无法让SUCCESS表单提交。我想这也:

jQuery form submit

下面是一个半功能小提琴代码:

http://jsfiddle.net/ZcgqV/

本质上发生的事情是这样的:

  1. 我绑定的方法通过onSubmit(而不是点击)向表单提交
  2. 提交时,它要求通过jQuery阿贾克斯()的远程服务器调用
  3. 如果回答是“待定”,重试每1秒,九次
  4. 如果失败,不提交表单
  5. 成功时,提交表单

无论我尝试什么,我都无法让表单在我想要的时候提交而不进入循环,或者在尝试远程服务器时不立即提交。

〜沮丧,试图-100-的东西 - 即失效-LY你...

下面的代码直接的情况下,你不喜欢小提琴:

var retries = 0; 
var success = false; 
var token = "toki wartooth is not a bumblebee"; 

$(document).ready(function() { 
    // Attach the action to the form 
    $('#tehForm').attr('onSubmit', 'onsubmit_action(event)'); 
}); 

function async(fn) { 
    setTimeout(fn, 1000); 
} 

function pollServer() { 
    $.ajax({ 
     type: "POST", 
     cache: "false", 
     url: "/remoteCall", 
     dataType: "json", 
     data: { 
      ref_token: token 
     } 
    }).done(function(data, code, jqXHR) { 

     switch (data.status) { 
     case "SUCCESS": 
      alert("Success"); 
      success = true; 

      // --> HERE IS WHERE I WANT THE FORM TO SUBMIT <-- 

      break; 

     case "PENDING": 
      if (retries < 9) { 
       retries += 1; 
       async(function() { 
        pollServer(); 
       }); 
      } else { 
       alert("Failed after 9 tries"); 
      } 
      break; 

     case "ERROR": 
      alert("Error"); 
      break; 

     default: 
      alert("Some kind of horrible error occurred"); 
      break; 
     } 

    }).fail(function(jqXHR, textStatus) { 
     var statusCode = jqXHR.status; 
     alert("Request failed: " + statusCode + " " + textStatus); 
    }); 

} 

function onsubmit_action(event) { 
     pollServer(); 
     if (success === false) { 
      // RETURN FALSE DIDN'T WORK, SO I FOUND THIS 
      event.preventDefault(); 
     } 
}​ 

编辑:

再次,这里真正的问题是我停止提交表单。在SUCCESS上,我希望提交表格。目前,如果我在SUCCESS中使用.submit(),则会再次调用AJAX,启动该过程。我想要的只是表单的行动,只有在成功的情况下才能开火。

+0

注意:我知道这是一个看似常见的问题,但我还没有遇到一个适合我的答案,这就是我问的原因。相信,我一直在阅读/尝试。 – Spanky 2012-08-16 23:19:56

+0

我真的不明白你的代码试图做什么,从我可以收集尝试设置ajax上下文:$('#tehForm');那么你可以使用$(this)// ==上下文so $(this).submit() – Philip 2012-08-16 23:24:50

+2

是否需要每隔1秒轮询一次服务器?如果没有,但你想要快速轮询,我建议调用一个函数,当你匹配PENDING的情况下,在完成的处理程序中执行另一个Ajax调用。我问的原因是每1秒是真的频繁,你肯定会从它疯狂的行为。将它绑定到完成的处理程序将保证您的浏览器可以像浏览器一样快速地触发调用(并且在大多数情况下,浏览器可以同时处理的最大4个Ajax调用似乎不是很有用)。 – brandwaffle 2012-08-16 23:25:43

回答

3

尝试使用尽可能多的原代码尽可能的;这里是一个解决方案:

邮政形式回传 http://jsfiddle.net/tpm7v/4/

帖子的形式通过Ajax http://jsfiddle.net/tpm7v/5/

var retries = 0, 
    token = "toki wartooth is not a bumblebee", 
    sendRequest, 
    handelResponse, 
    postFormToServer, 
    $theForm = $('#tehForm'); 

$(document).ready(function() { 
    // Attach the action to the form 
    $theForm.bind('submit', onsubmit_action); 
}); 

sendRequest = function() { 
    $.ajax({ 
     type: "POST", 
     cache: "false", 
     url: "/remoteCall", 
     dataType: "json", 
     data: { 
      ref_token: token 
     }, 
     success: handelResponse 
    }); 
}; 

postFormToServer = function() { 
    $.ajax({ 
     type: "POST", 
     cache: "false", 
     url: "/remoteCallToTakFormData", 
     dataType: "json", 
     data: $form.serialize(), 
     success: function() { 
      alert('success!'); 
     } 
    }); 
}; 

handelResponse = function(data, code, jqXHR) { 
    switch (data.status) { 
     case "SUCCESS": 
      postFormToServer(); 
      break; 

     case "PENDING": 
      if (retries < 9) { 
       retries += 1; 
       setTimeout(sendRequest , 1000); 
      } else { 
       alert("Failed after 9 tries"); 
      } 
      break; 

     case "ERROR": 
      alert("Error"); 
      break; 

     default: 
      alert("Some kind of horrible error occurred"); 
      break; 
     } 
}; 

function onsubmit_action(evt) { 
    evt.preventDefault(); 
    sendRequest(); 
} 
​ 
​ 

记住我打算把你提供的代码。你应该能够移植这个来和你的实际实现一起工作。您可能还想尝试诸如https://github.com/webadvanced/takeCommand之类的帮助清理所有Ajax调用。

+0

这应该可行,但我建议还设置一个var,它决定你是否设置了重试计时器,因此你只能调用setTimeout一次。您也可以执行var timer_id = setTimeout(),以便稍后可以在尝试以9次未成功命中端点后使用clearTimeout()取消超时。 – brandwaffle 2012-08-16 23:51:20

+0

这看起来很有希望,我会在尝试之后回复你。谢谢。 – Spanky 2012-08-16 23:51:34

+0

@Spanky让我知道它是怎么回事。可能需要调整一些东西才能使其工作。很乐意回答任何问题。 – Paul 2012-08-16 23:53:26

0

请参阅我的评论上面的详细信息,但我认为你在这里看到的问题是这样的:

每次pollServer()火灾,它不仅做一套Ajax调用,但其准备做根据重试循环每秒调用9次可能的ajax。既然你正在用async()方法设置另一个pollServer()调用,你基本上将你的ajax调用混合在一起。你想从你的重试循环中获得ajax调用,那么你至少应该只有一秒的请求,而不是1,然后是2,然后是3等等。我可能读了错误的代码,但这是我最好的猜你在看什么。

更新:我不确定我的解释是否清楚,因此我想添加一些其他信息。基本上,每次调用pollServer()并获得一个PENDING响应时,它都会调用异步,它会注册一个setTimeout()。 setTimeout()每秒都会继续运行,执行pollServer(),然后调用异步,它会注册另一个setTimeout(),它也会每秒运行一次。现在你有两个函数,每个函数都会调用setTimeout(),假设他们仍然得到PENDING作为来自服务器的响应。所以在2轮失败的调用之后,你有4次setTimeout()调用,每次调用一次ajax调用(和一个新的setTimeout)。

+0

谢谢。我没有看到这种失控/复合行为。这些电话会像他们应该去的一样,1s,2s,3s,但是当成功达到时,我无法获得表格发布。如果我在以下情况下调用form.submit():SUCCESS,它会重新开始。 – Spanky 2012-08-16 23:33:23

+0

如果我在异步调用中不这样做,那么setTimeout根本不起作用,并且所有9次都尽可能快地开火。这是它尊重暂停的唯一方式。请参阅:http://fitzgeraldnick.com/weblog/35/ – Spanky 2012-08-16 23:44:08

0

首先它应该是:$('#tehForm').submit(onsubmit_action);$('#tehForm').on("submit",onsubmit_action);或类似的东西。切勿使用字符串形式传递函数。它使用邪恶的eval语句。

接下来,POST后数据已经提交。这是发布的全部原因。为什么需要完成部分中的各种错误处理?失败应该处理错误处理。

如果你问有关如何在超时后重试,试试这个: Is it possible to check timeout on jQuery.post()?

我相信超时将陷入失败。

那么试试这个:

var retries = 0, 
    max_tries = 9, 
    success = false, 
    token = "toki wartooth is not a bumblebee"; 

$(document).ready(function() { 
    // Attach the action to the form 
    $('#tehForm').on("submit",submit_the_form); 
}); 

function submit_the_form(e){ 
    var dfd = $.ajax({ 
     url : "sendTokenPolling", 
     data : {"token":token}, 
     timeout : 5000 //you may want 1000, but I really think that is too short 
    }); 
    dfd.done(function(){ 
     //success, form posted 
    }); 
    dfd.fail(function(){ 
     //did not work/timedout 
     if (retries < max_tries){ 
     retries += 1; 
     submit_the_form(e); 
     } 
    }); 
} 
+0

帕里斯,我相信OP是在服务器可能响应的情况下,但特定的后端进程可能仍然在运行,这将需要客户端等待。在这种情况下,失败方法永远不会运行,客户端将不会尝试重新提交表单。我不相信这个回应永远不会超时(至少不是在OP所考虑的'标准'情况下)。 – brandwaffle 2012-08-16 23:44:04

+0

AJAX POST是一个远程服务器,而不是本地页面。我将当前表单的活动从远程调用的响应中解脱出来。 – Spanky 2012-08-16 23:45:22

+0

另外,是的,谢谢,我知道邪恶的东西,这又是一个例子。但是,谢谢,没有足够的人认出这一点。 – Spanky 2012-08-16 23:46:25