这个问题已被多次询问和回答,答案是“从成功回调中调用另一个函数”不幸的是,由于几个原因,我无法弄清楚如何在我的情况下使这个答案有效。/ p>
对于初学者来说,被调用的ajax是ajaxForm的提交函数。
在一个地方我调用ajax submit,调用函数ITSELF需要返回true或false,具体取决于AJAX调用的成功和从它返回的一些数据。这基于多个位置使用的选项卡窗口小部件:您可以将功能绑定到选项卡,该选项卡在单击选项卡时运行。选项卡小部件本身希望此函数返回true(显示选项卡)或false(不显示选项卡)。由于此标签窗口小部件在我的网站中使用,因此更改此行为最多是困难的。
表单本身可以从多个地方提交,所以我不能简单地从成功处理程序中调用此选项卡函数的其余部分(即使我重新编写了tab处理程序以异步工作),因为在其他地方提交表格时,这可能不是对成功的适当回应。在这种情况下,我想显示用户单击的选项卡。在另一种情况下,我想重新加载页面或重置表单(新的,空白表格),在第三种情况下,我想要转到另一页面。但在所有情况下,它都是对提交相同表格的回应。
我想我可以这样做,所以当点击时,标签总是会切换,然后(通过设置标志或其他东西,这样只有在选项卡点击后才会发生)如果提交不起作用,请切换回来,但这感觉非常糟糕。那么,有没有办法让调用函数等到回调完成之后?还是有另一种方法来构建我没想到的东西吗?
编辑: 我现在有一个当前结构available here的jsfiddle。一般的想法是,在我知道jquery有一个标签小部件之前,我需要标签,所以我写了自己的标签。它有效,所以我没有理由改变:-)。
在准备好文档时,具有相应类的每个按钮都会分配一个单击处理程序。流程如下:
所以我的困境是,为了防止显示标签,我需要在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");
}
答案 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
来模拟异步请求)