【问题标题】:Pause the function execution flow till ajax request completes暂停函数执行流程,直到 ajax 请求完成
【发布时间】:2016-09-08 12:07:48
【问题描述】:

我似乎遇到了典型的“异步问题”,而我却找不到解决方案。

我有一个bootstrap form wizard,它只是一个临时的标签/幻灯片有点东西。我所有的“步骤”都是各自标签/幻灯片中的表格。

它有一组下一个/上一个按钮来浏览幻灯片。 并且它在移动到下一张幻灯片之前提供了一个函数回调。 在其中(回调)我正在“客户端验证”当前幻灯片中的表单,如果它经过验证,那么我将使用 ajax 提交表单。一旦我得到服务器的响应,我将决定是返回 true(继续下一张幻灯片)还是返回 false(停止导航到下一张幻灯片)。

我已经调查了..

  • Using callbacks 但它不会阻止插件继续到下一张幻灯片,顺便说一句,这是一个硬编码的成功消息,所以在我们等待 ajax 响应时,向导已经移动到下一张幻灯片。
  • 使用 async:false 但这会像疯了一样挂起浏览器(按设计),直到请求完成,所以没有挂起这正是我想要的。

我的代码如下。

JS.

  jQuery('#progressWizard').bootstrapWizard({
            'nextSelector': '.next',
            'previousSelector': '.previous',
            onNext: function (tab, navigation, index) {
                if (index == 1) { // Here I am deciding which code to execute based on the current slide/tab (index)
                    if (jQuery("#paymentstep1").data('bValidator').validate()) {
                        var data = new FormData(jQuery('#paymentstep1')[0]);
                        jQuery("#cgloader").fadeIn();
                        var success = false;
                        jQuery.ajax({
                            type: "post",
                            async: false,
                            contentType: false,
                            processData: false,
                            url: "xyz.php",
                            dataType: "json",
                            data: data,
                            success: function (r) {

                              return r;
                            }
                          });
                        }....

【问题讨论】:

  • 第一种方法是唯一真正可接受的解决方案。如果这意味着更改向导插件,我仍然强烈推荐它。使用async: false 绝不是一种选择,因为正如您所见,它会挂起浏览器直到请求完成。这将使浏览器在用户看来就像崩溃一样,这是糟糕的用户体验。解决方法是使用异步请求。
  • 停止导航到下一张幻灯片,然后在回调时重新启动

标签: javascript jquery ajax


【解决方案1】:

docsonNext 说:

单击下一个按钮时触发(返回 false 以禁用 进入下一步)

所以只需从您的处理程序返回false。在 AJAX 成功回调中,调用next 前进到下一张幻灯片。

var requestCompleted = false;
jQuery('#progressWizard').bootstrapWizard({
  'nextSelector': '.next',
  'previousSelector': '.previous',
  onNext: function (tab, navigation, index) {
    if (index == 1) { // Here I am deciding which code to execute based on the current slide/tab (index)
      if (jQuery("#paymentstep1").data('bValidator').validate()) {
        if(!requestCompleted) {
          var data = new FormData(jQuery('#paymentstep1')[0]);
          jQuery("#cgloader").fadeIn();
          var success = false;
          jQuery.ajax({
              type: "post",
              url: "xyz.php",
              data: data,
              // ...
              success: function (r) {
                requestCompleted = true;
                jQuery('#progressWizard').bootstrapWizard('next');
                return r;
              }
            });
          return false;
        }
      }
    }
  });

【讨论】:

  • 但是如果我在ajax中调用next成功,“onNext”回调中的代码不会再次被触发吗?再次发出 ajax 请求?
  • 当然。因此,请使用变量来跟踪您是否已发出请求。
  • hm... tbh,我一直牢记这一点,但不确定这是否是正确的方法,所以如果我找不到更好的解决方案。谢谢。
【解决方案2】:

使用承诺?

在 jQuery 中有一个承诺。这是语法。

$.when( $.ajax( "test.aspx" ) ).then(function( data, textStatus, jqXHR ) {
  alert( jqXHR.status );    });

现在在 javascript 中也有了 Promise!

var promise = new RSVP.Promise(function(fulfill, reject) {
  (...)
});

那么,

promise.then(onFulfilled, onRejected);

【讨论】:

  • 谢谢克里斯克拉克!那个承诺代码救了我的培根!
【解决方案3】:

我会使用不同的事件来执行您的异步代码。这个想法是使用 onTabChange (考虑使用 onTabClickonTabShow ),这样你就可以防止移动到下一个选项卡 bootstrapWizard(); 将如何导航。只有在一切通过后,才能以编程方式触发下一个选项卡,您必须了解如何操作。

$('element').bootstrapWizard('onTabShow', function(){

  //Do everything you need here and show next tab
  $('element').bootstrapWizard('show',3);
  return false;
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-20
    • 1970-01-01
    • 2023-04-01
    相关资源
    最近更新 更多