防止 JavaScript 调用延迟出现
prevent javascript calls from having delayed appearance
我遇到了问题,即在拨打电话时没有出现简单的视觉效果,而是被大大延迟,几乎直到它没有实际意义。
我正在尝试同步获取一些数据(是的,没错,不是异步的(,在它发生时放置一个"等待"指示器,然后在获取完成后隐藏指示器。问题是执行执行该指标的代码时没有出现;jQuery show(( 调用的可视结果在调用发生时不会发生 - 它会等到数据获取完成。我已经通过将时间戳记录到控制台来确认 show(( 调用确实在数据获取之前发生。
奇怪的是,控制台日志记录在视觉上也会延迟,即使时间戳确认代码正在发生
。最后但并非最不重要的一点是,如果我在数据获取之前引入对 alert(( 的调用,那么视觉内容都会在警报上升时发生,它不会等到数据获取完成。
这是代码。再次注意,数据获取是对 $.ajax(( 的同步调用(即 async: false(。
fillInClient: function(clientId) {
var result, spinner;
console.log("spinning at " + ($.now()));
spinner = $("tr#client_" + clientId + " .spinner");
spinner.show();
// if I call alert("foo") here, I see both of the spinner.show() and
// the first console.log immediately. Then after a few seconds,
// I see the hide, and the second console.log
// Without alert(), I never see the show() and the first console.log
// doesn't appear until after this:
// this takes several seconds
result = $.ajax({
type: "GET",
url: "/advisor/householding/accounts?user=" + clientId,
async: false
});
spinner.hide();
console.log("stopping at " + ($.now()));
return result;
}
这是我在控制台中看到的内容。请注意,它们有效地同时出现,但您可以从时间戳中看到它们被调用间隔几秒钟。
spinning at 1418933857688
stopping at 1418933862374
提前感谢...
浏览器将尝试每n
毫秒重新绘制一次,如果浏览器在该时间点被阻止(调用堆栈不为空(,它将等到堆栈为空进行渲染。在本例中,你显示微调器,发送同步 ajax 请求,然后隐藏微调器。这意味着在显示微调器和隐藏微调器之间,调用堆栈永远不会清空,因此浏览器永远不会重新绘制,因此在浏览器呈现微调器之前,您的微调器是隐藏的。
要解决此问题,您需要将阻塞的代码段移出堆栈,以便在浏览器被阻止之前进行浏览器渲染。这通常是使用 setTimeout
来完成的,但是,这将完全破坏您的代码的工作方式,以至于它可能是一个异步请求。以下是您的代码仍在使用 setTimeout
的同步请求:
fillInClient: function(clientId, doneCallback) {
var result, spinner;
console.log("spinning at " + ($.now()));
spinner = $("tr#client_" + clientId + " .spinner");
spinner.show();
setTimeout(function () {
var result = $.ajax({
type: "GET",
url: "/advisor/householding/accounts?user=" + clientId,
async: false
});
doneCallback && doneCallback(result);
spinner.hide();
console.log("stopping at " + ($.now()));
}, 20);
//return result;
}
如您所见,您的函数不再返回结果,而是必须进行回调。此时,您不妨将其设置为异步请求并丢失setTimeout
。
fillInClient: function(clientId, doneCallback) {
var result, spinner;
console.log("spinning at " + ($.now()));
spinner = $("tr#client_" + clientId + " .spinner");
spinner.show();
$.ajax({
type: "GET",
url: "/advisor/householding/accounts?user=" + clientId
})
.done(doneCallback)
.always(function () {
spinner.hide();
console.log("stopping at " + ($.now()));
});
}
这是我的建议。 对同步请求使用 AJAX 是完全没有必要的。 若要为异步代码提供同步感觉,请使用回调。 下面是一个示例:
fillInClient: function(clientId) {
var result, spinner;
console.log("spinning at " + ($.now()));
spinner = $("tr#client_" + clientId + " .spinner");
spinner.show();
result = $.ajax({
type: "GET",
url: "/advisor/householding/accounts?user=" + clientId,
complete: function (){
spinner.hide();
console.log("stopping at " + ($.now()));
//Other logic to run after the call completes
}
});
}
因此,您在同步函数之后拥有的所有内容,我已移至complete()
函数,因此它只会在 AJAX 调用完成后运行。 我想不出任何正当的理由以另一种方式做到这一点。
- jQuery延迟了ajax调用的循环
- 使用jquery延迟对象链接多个ajax调用
- jQuery通过嵌套的ajax调用延迟对象
- jQuery 延迟的 AJAX 调用返回值
- 如何在 JS 中调用 2 次或更多次时延迟函数执行
- AJAX 调用和表单提交之间的延迟
- 如何按顺序调用延迟函数
- 使用promise或setTimeout确定延迟函数的调用顺序
- 如何调用具有延迟的函数
- 将动态参数应用于 JavaScript 函数,但延迟调用
- 延迟调用 dojo widget 中的函数,直到设置全局变量
- 多个 ajax 调用的延迟调用
- AngularJS:如何用延迟调用递归函数
- 在异步代码块中处理的多个ajax延迟调用的数组,后面是同步的最终代码块
- 如何处理嵌套的jquery延迟调用
- 是否使用负延迟调用setTimeout
- 顺序的、依赖的延迟调用
- Angular服务的Jasmine测试不能解决延迟调用
- 如何一个接一个地延迟调用javascript函数
- 延迟1调用setTimeout的目的是什么