我有一个问题,一个简单的视觉效果没有出现时,打电话时,而是被大大推迟,几乎是直到点,它是没有意义的。
我试图同步获取一些数据(是的,这是对的,而不是异步的),在发生时设置一个“等待”指示符,然后在get完成后隐藏该指示符。问题是在执行代码时没有出现指示符;在调用时不会出现jQuery show()调用的可视化结果--它正在等待数据获取完成。我已经确认,show()调用确实发生在数据通过将时间戳记录到控制台而得到之前。
然而,奇怪的是,控制台日志记录也会在视觉上延迟,即使时间戳可以确认代码是在您预期的情况下发生的。
最后,但至少,如果我在数据获取之前引入一个警告()调用,那么当警报上升时,所有的可视内容都会发生,它不会等到数据获取完成。
这是密码。请再次注意,数据get是对$.ajax()的同步调用(即异步: 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
提前谢谢..。
发布于 2014-12-18 13:10:21
浏览器将尝试重新绘制每个n
ms,如果浏览器在那个时候被阻塞(调用堆栈不是空的),它将等到堆栈为空才呈现。在您的示例中,您将显示spinner,发送同步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()));
});
}
发布于 2014-12-18 13:10:04
这是我的建议。对同步请求使用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调用完成之后,它才会运行。我想不出有什么合理的理由去做这件事。
https://stackoverflow.com/questions/27555405
复制相似问题