暂停函数执行流程,直到 ajax 请求完成

Posted

技术标签:

【中文标题】暂停函数执行流程,直到 ajax 请求完成【英文标题】:Pause the function execution flow till ajax request completes 【发布时间】: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 绝不是一种选择,因为正如您所见,它会挂起浏览器直到请求完成。这将使浏览器在用户看来就像崩溃一样,这是糟糕的用户体验。解决方法是使用异步请求。 停止导航到下一张幻灯片,然后在回调时重新启动 【参考方案1】:

docs 对 onNext 说:

单击下一个按钮时触发(返回 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;
);

【讨论】:

以上是关于暂停函数执行流程,直到 ajax 请求完成的主要内容,如果未能解决你的问题,请参考以下文章

ajax怎样再次执行?

我如何控制 GWT 中的执行流程?

redux-thunk:暂停组件执行,直到 Action Creator 完成

Unity:如何暂停执行直到函数终止,以便不跳过任何帧

jvmti agent的加载与回调函数的执行分析

不使用回调函数的ajax请求实现(async和await简化回调函数嵌套)