Suppose this is the logic that I want :
// On fail return status = 500, else success will return PDF bytestream
function request() {
return $.ajax({
url: url,
async:false,
// other properties
});
}
$('#action').click(function(e) {
$("#loading").fadeIn("slow"); // display loading
while(true) {
if(request().status != 200) {
delay(3000);
} else { break; }
}
$("#loading").fadeOut("slow"); // hide loading
});
For testing delay without iteration and request, this code works well :
$(document).ready(function(){
$('#action').click(function(e) {
$("#loading").fadeIn("slow");
setTimeout(function() {
$("#loading").fadeOut("slow");
}, 5000);
e.preventDefault();
});
});
Problem started when I put some loops and request inside, like this :
var isOk;
$(document).ready(function(){
$('#action').click(function(e) {
$("#loading").fadeIn("slow");
while(true) {
request().always(function(jqXHR){
console.log(jqXHR);
if(jqXHR.status == 500) {
isOk = false;
setTimeout(function(){console.log("False")}, 3000);
} else { isOk = true; }
});
if(isOk) {break};
}
$("#loading").fadeOut("slow");
e.preventDefault();
});
});
It's like there's no delay in between iteration. The loading symbols fadeIn and fadeOut instantly. Any idea how to do the correct delay for iteration ?
答案 0 :(得分:3)
使用promises(技术上,在此示例中为jQuery Deferred但相同的概念)来修复流程,并为您节省很多麻烦:
$('#action').click(function(e) {
$('#loading').fadeIn('slow'); // display loading
$.ajax(url).always(function (e) {
$('#loading').fadeOut('slow'); // hide loading
});
});
请注意,我使用.always()
......即使出现错误,我们仍会隐藏加载指标。您可以为.fail()
添加另一个处理程序以捕获错误。
更好的是,使用.show()
和.hide()
,并将CSS动画用于任何这样的渐变样式。虽然在这种情况下不太重要,但它使得这些转换在JavaScript中的浏览器引擎中得到了极大的优化,同时将应用程序逻辑与样式分离得更多。
答案 1 :(得分:1)
You should call .fadeOut() when ajax request is resolved, like this:
$(document).ready(function(){
$('#action').click(function(e) {
e.preventDefault();
$("#loading").fadeIn("slow");
performRequest();
});
function performRequest() {
request()
.always(function(jqXHR){
console.log(jqXHR);
if(jqXHR.status === 500) {
console.log("False");
var t = setTimeout(function() {
performRequest(); // retry after 3sec.
clearTimeout(t);
}, 3000);
} else {
onRequestSuccess(); // success
}
});
}
function onRequestSuccess() {
$("#loading").fadeOut("slow");
}
});
答案 2 :(得分:0)
Since the ajax call is asynchronous
, it doesn't wait before executing the next line of code.
If you want to fadeOut on finish, run fadeOut()
inside the callback function of the ajax call, or within this function.
Put the following right where you have //other properties
:
complete: function(jqXHR, textStatus) {
$("#loading").fadeOut("slow");
}
You have to use delay()
, setTimeout()
otherwise.
Delay:
$("#loading").fadeIn(2000);
$("#loading").delay(2000).fadeOut(2000);
setTimeout:
$("#loading").fadeIn(2000);
setTimeout(function(){
$("#loading").fadeOut(2000);
}, 2000);
Just another suggestion, handle errors in your Ajax call, rather than in while loops:
error: function(jqXHR, textStatus, errorThrown) {
setTimeout(function() {
request();
}, 3000);
}
And another, take @Brad 's advice and use CSS Animations instead.
答案 3 :(得分:0)
Here is what I was talking about. In this example, the fadeOut is executed after fadeIn is done as a callback. I included a timeout to show you can do that as well.
$(function() {
$("#test").fadeIn(2000, function() {
setTimeout(function() {
$("#test").fadeOut(2000);
}, 1000);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="test" style="display:none">
TEST DIV
</div>
If you want the loading to fade in before each ajax call and fade out after success, then you'll need to handle the fade out in your ajax success callback. Using your code, this would fade out upon completion.
$(document).ready(function(){
$('#action').click(function(e) {
$("#loading").fadeIn("slow");
while(true) {
request().always(function(jqXHR){
console.log(jqXHR);
if(jqXHR.status == 500) {
setTimeout(function(){console.log("False")}, 3000);
} else {
$("#loading").fadeOut("slow");
break;
}
});
}
e.preventDefault();
});
});