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

query ajax- change return value of calling function based on AJAX response?

本文关键字:调用 函数 返回值 ajax- 根据 ajax 响应 查询      更新时间:2023-09-26

这个问题已经被问了很多次,答案都是"从成功回调中调用另一个函数"。不幸的是,由于几个原因,我不知道如何在我的情况下让这个答案发挥作用。

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

  1. 在我调用ajax提交的一个地方,调用函数ITSELF需要返回true或false,这取决于ajax调用的成功与从中返回的一些数据。选项卡小部件本身期望此函数返回true(显示选项卡)或false(不显示选项卡)。由于这个选项卡小部件在我的整个网站上都在使用,所以改变这种行为充其量是很困难的。

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

我想我可以做到,当点击时,选项卡总是切换,然后(通过设置标志或其他东西,只有在点击选项卡后才会发生)如果提交不起作用,切换回来,但感觉很糟糕。那么,有什么方法可以让调用函数等待回调完成吗?或者有没有其他方法来构建我没有想到的东西?

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

在文档就绪时,具有适当类的每个按钮都会分配一个单击处理程序。流程如下:

  1. onClick处理程序触发beforeShow事件来运行绑定到选项卡对象的函数(如果有的话)
  2. beforeShow函数在显示选项卡之前执行所需的任何类型的准备工作(例如加载数据)。如果需要,可以在此处将选项卡对象的"show"数据设置为false,以防止显示选项卡,例如在当前选项卡上检测到需要在切换前修复的错误
  3. beforeShow函数返回后,onClick处理程序将检查"show"数据是否设置为false,如果没有,则隐藏所有其他选项卡并显示单击的选项卡

因此,我在这里的困境是,为了防止选项卡被显示,我需要在onClick处理程序检查之前(即在beforeShow函数期间)将选项卡对象的"show"数据设置为false。但是由于AJAX回调是异步的,所以直到onClick处理程序完成之后,我才得到AJAX的结果来判断是否应该显示选项卡,从而显示选项卡

正如我所提到的,我可以做一些事情,比如存储当前选项卡,如果ajax结果指示不显示新选项卡,请切换回来,但这对我来说是错误的。

点击处理程序:

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");
}

这正是您想要的

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);
}

我们在表单操作url上发布synchronous,序列化表单的数据,这样我们就可以使用它进行ajax post。这应该会附带一些小的调整。

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

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

这是一个异步实现的方法。

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);
}

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