我有一个问题,即在进行通话时没有出现简单的视觉效果,而是大幅延迟,直到它没有实际意义。
我试图同步获取一些数据(是的,这是正确的,而不是异步的),提出等待"等等。指示器发生时,然后在完成后隐藏指示器。问题是当执行代码执行时,指示符没有出现;在进行调用时,jQuery show()调用的可视结果不会发生 - 它等待数据完成。我已经确认show()调用确实在数据到达之前通过将时间戳记录到控制台来发生。
奇怪的是,即使时间戳确认代码正在发生时,控制台日志记录也会在视觉上延迟。
最后但是至少,如果我在数据获取之前引入了对alert()的调用,那么可视化的东西都会在警报响起时发生,它不会等到数据完成后才会发生。
这是代码。再次注意,数据get是对$ .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
提前致谢...
答案 0 :(得分:0)
这是我推荐的。完全不需要使用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调用完成后运行。我想不出有任何其他有效理由这样做。
答案 1 :(得分:0)
浏览器将尝试每n
ms进行一次重绘,如果浏览器在该时间点被阻塞(调用堆栈不为空),它将等待堆栈为空渲染。在您的情况下,您将显示微调器,发送同步ajax请求,然后隐藏微调器。这意味着在显示微调器和隐藏微调器之间,callstack永远不会清空,因此浏览器永远不会重新绘制,因此在浏览器渲染之前隐藏了微调器。
要解决此问题,您需要将阻止的代码段移出堆栈,以便在浏览器被阻止之前进行浏览器渲染。这通常使用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()));
});
}