查询ajax-根据AJAX响应更改调用函数的返回值?

时间:2014-08-26 19:40:19

标签: javascript jquery ajax

这个问题已被多次询问和回答,答案是“从成功回调中调用另一个函数”不幸的是,由于几个原因,我无法弄清楚如何在我的情况下使这个答案有效。

对于初学者来说,被调用的ajax是ajaxForm的提交函数。

  1. 在一个地方我调用ajax submit,调用函数ITSELF需要返回true或false,具体取决于AJAX调用的成功和从它返回的一些数据。这基于多个位置使用的选项卡窗口小部件:您可以将功能绑定到选项卡,该选项卡在单击选项卡时运行。选项卡小部件本身希望此函数返回true(显示选项卡)或false(不显示选项卡)。由于此标签窗口小部件在我的网站中使用,因此更改此行为最多是困难的。

  2. 表单本身可以从多个地方提交,所以我不能简单地从成功处理程序中调用此选项卡函数的其余部分(即使我重新编写了tab处理程序以异步工作),因为在其他地方提交表格时,这可能不是对成功的适当回应。在这种情况下,我想显示用户单击的选项卡。在另一种情况下,我想重新加载页面或重置表单(新的,空白表格),在第三种情况下,我想要转到另一页面。但在所有情况下,它都是对提交相同表格的回应。

  3. 我想我可以这样做,所以当点击时,标签总是会切换,然后(通过设置标志或其他东西,这样只有在选项卡点击后才会发生)如果提交不起作用,请切换回来,但这感觉非常糟糕。那么,有没有办法让调用函数等到回调完成之后?还是有另一种方法来构建我没想到的东西吗?

    编辑: 我现在有一个当前结构available here的jsfiddle。一般的想法是,在我知道jquery有一个标签小部件之前,我需要标签,所以我写了自己的标签。它有效,所以我没有理由改变:-)。

    在准备好文档时,具有相应类的每个按钮都会分配一个单击处理程序。流程如下:

    1. onClick处理程序触发beforeShow事件以运行绑定到选项卡对象的函数(如果有)
    2. beforeShow函数在显示选项卡之前执行所需的任何类型的准备工作(例如加载数据)。如果需要,可以在此处将tab对象的'show'数据设置为false,以防止显示选项卡 - 例如,如果在切换之前需要修复的当前选项卡上检测到错误。
    3. 在beforeShow函数返回后,onClick处理程序检查“show”数据是否设置为false,如果没有隐藏所有其他选项卡并显示单击的选项卡。
    4. 所以我的困境是,为了防止显示标签,我需要在onClick处理程序检查它之前将标签对象的'show'数据设置为false(即在beforeShow函数期间)。但是由于AJAX回调是异步的,我不会得到AJAX的结果,看看我是否应该在onClick处理程序完成之后显示选项卡 - 从而显示选项卡。

      正如我所提到的,我可以执行类似存储当前选项卡的操作,如果ajax结果显示NOT不显示新选项卡,请切换回来,但这对我来说感觉不对。

      点击处理程序:

      function changeTab(){
          var jqButton=$(this);
          jqButton.data('show',true); //start by assuming we will show the tab.
          if(jqButton.hasClass("current")) //don't do anything if switching to the current tab
              return;
      
          //run the "before show" function, if any.
          jqButton.trigger('beforeShow');
          var showTab=jqButton.data('show'); //see if the show flag has been set to false
      
          if(showTab===false) //if no before show function, then showTab is null, not false
              return; //if false, then don't show the tab.
      
          $(".tabDiv").hide();
      
          //run any "after hide" scripts bound to the current tab
          $('.tabButton.current').trigger('afterHide');
      
          var requestedDiv=jqButton.val(); //the "value" of the tab button is the ID of the tab content div
          $("#"+requestedDiv).show(); //may show nothing, if no div exists for the current tab.
          $(".tabButton").removeClass("current"); //remove the current class from all tab buttons, so it will only be applied to the new current tab button.
          jqButton.addClass("current");
      }
      

2 个答案:

答案 0 :(得分:2)

这几乎是你想要的

function tab2BeforeShow(){
    var $form = $('#SomeajaxFormObject'); // This is the form you want to submit
    // I'd probably show some load indicator here
    var result;
        $.ajax({
        url: $form.attr('action'),
        type: 'POST',
        data: $form.serialize(),
        async: false,
        success: function(response) {
            result = true; // set the result variable declared in outer function
        },
        error: function() {
            result = false; // bad response - dont show new tab
        }
    });

    // Hide your load indicator now

    // since we declared async: false on the ajax request, 
    // we can be positive that result is set to a boolean value at this point
    $(this).data('show', result);
}

我们在您的表单操作网址上发布synchronous帖子,序列化表单的数据,以便我们可以使用它进行ajax POST。这可能会有所下降,可能会有一些细微的调整。

这里的关键因素是我们将data设置为$form.serialize()并将async设置为false,因此浏览器在请求工作时不会继续执行。

如果有任何方法可以避免使用同步ajax,你真的应该这样做。如果你无法避免,这对你有用。请注意,如果服务器挂起,它也将挂起您的客户端。

答案 1 :(得分:1)

这是一种异步执行的方法。

beforeShow处理程序接受可选的promise参数:

var eventParams = {
    promise: null
};
jqButton.trigger('beforeShow', eventParams);

在处理程序本身中,必要时创建一个promise:

function tab2BeforeShow(e, eventParams) {
    eventParams.promise = $.Deferred();
    $.ajax(... async code...
        var showTab = [some value received from request];
        eventParams.promise.resolve(showTab);
    );
}

然后,如果创建了promise,则使用promise链而不是同步函数调用:

// doShowTab is the logic that actually shows/hides a tab
if (eventParams.promise) {
  // use promise instead
  eventParams.promise.then(doShowTab);
} else {
  // beforeShow handler didn't return a promise, assume showTab=true
  doShowTab(true);
}

小提琴:http://jsfiddle.net/669v1Lcd/(我使用setTimeout来模拟异步请求)