I have a simple question (but the answer does not seem to be simple).
I have a synchronous AJAX call in my code and I want to call a function before this synchronous call.
The function I want to call is simply
$.blockUI();
from jQuery BlockUI Plugin.
I simply tried to put that line before my $.ajax call but the blockUI seems to be called after the synchronous call.
I then tried to use the beforeSend option of $.ajax, same problem as above.
Thanks in advance for any answer you could bring (except using asynchronous call which is just impossible in my case...)
Code is available here : http://jsfiddle.net/vWsus/2/
Synchronous calls are bad, they lock up the browser and if the call is not returned, it is not a good user experience. The problem you have is the synchronous call is locking up the browser so the DOM never has time to redraw. You need to give time for the DOM to update, so set a timeout before making the Ajax call.
$.blockUI({ message: '<p>foo</p>' });
window.setTimeout( ajxCallFnc, 100);
In your case, it's not that the blockUI is called after the synchronous call, it's just that the synchronous request prevents the display reflow (which generally happens "sometimes later" than your actual DOM manipulation). And as you said, when you tried & called blockUI before the call to ajax rather than from inside the beforeSend callback, you end up with pretty much the same result.
There is nothing that can be done in jQuery to prevent this behaviour since it is not a jQuery bug (nor a browser one per se, seeing as synchronous xhr requests are supposed to freeze the browser anyway and that nothing says the browser has to carry on with the reflow in that instance).
All I can recommand is to NEVER EVER use synchronous requests. Asynchronous ones are easy enough to deal with.
You can take a look on Why You Should Use XMLHttpRequest Asynchronously
$.blockUI has a onBlock function. Try something like this:
$.blockUI({
message: '<img id="processing" src="images/loading.gif" />',
onBlock: function() {
// make your sync call here
$.ajax({
type: 'POST',
cache: false,
async: false,
url: blahblah,
dataType: 'json'
}).done(function(data){
//process response
});
}
});
this.notifyFixed=function(type,msg,callback){
this.showNotification(type, msg);
window.setTimeout(function(){
if(typeof callback ==="function"){
callback();
}
},100);
};
I had a notifyFixed function that I wanted to do before I make my ajax call, was running into same problems, so I added timeout and a callback function similar to epascarello that seemed to work fine for me.
So hopefully similar solution can help other people
Related
Possible duplicate: Same problem (unresolved)
I show loading DOM before the Ajax call and after the Ajax call, I hide it. For some reason, the loading image appears only after ajax call completes. The result is that the loading image doesn't even appear unless I put delay(#).hide(0) The code is the following:
$("#loading-popup").show();
$.ajax({
// ajax here
});
$("#loading-popup").hide(0);
I have tested on other Ajax calls on my website and the same problem occurs. Has anyone got this resolved? I am using Chrome 26.
EDIT: I forgot to specify that I am using synchronous ajax call. (async: false)
It depends on whether the ajax call is synchronous or asynchronous.
For asynchronous ajax call, the following works:
$("#loading-popup").show();
$.ajax({
type: 'POST',
// other parameters
success: function(yourdata)
{
$("#loading-popup").hide();
}
For synchronous ajax call, it does NOT. Ajax gets executed first and all other processes are blocked/queued.
A way around it is to use setTimeOut like this:
setTimeout(function () {
$("#loading-popup").show();
$.ajax({
type: 'POST',
async: false,
// other parameters
//
// other codes
});
$("#loading-popup").hide();
}, 10);
But because it is synchronous, the loading GIF will NOT animate and just become a static image (At least for Chrome that is)
I guess there are only two solutions:
1) use asynchronous ajax call
2) use static loading image
I know Im a bit late to the party on this, but for future reference if you want to have a loading animation AND use a synchronous ajax call AND have it animate in chrome, you can use this third party ajax script: http://fgnass.github.io/spin.js/#!
Spin.js dynamically creates spinning activity indicators that can be
used as resolution-independent replacement for AJAX loading GIFs.
I use it extensively and it works perfectly for me.
This could be another way.
var $ani = $('#loading-popup').hide();
$(document)
.ajaxStart(function () {
$ani.show();
})
.ajaxStop(function () {
$ani.hide();
});
i'm not sure if this problem is already resolved, but try this:
$("#loading-popup").show();
$.ajax({
// ajax here
success: function(data) {
$("#loading-popup").hide();
}
});
let me know if this works..
The ajax() is async function and the statements under it might execute before the ajax call is completed. You have to hide in success or done function.
$("#loading-popup").show();
$.ajax({
// ajax here
}).success(data){
$("#loading-popup").hide(0);
})
I'm confused by this synchronous jquery ajax request. The ajax loader doesn't show until after the ajax call is complete. I'm well aware that the synchronous request will block the UI, but why does it start blocking before that line of code has been hit? I must be misunderstanding something fundamental about execution order.
$("#ajax-loader").show(1, function(){
$.ajax({
url: xxx,
type: "POST",
async: false,
success: function (data) {
hideAjaxLoader();
}
});
});
Even though jQuery believes the animation is complete when it calls your code containing the synchronous ajax call, that doesn't mean the browser has done all of its work to render the result before that callback. And since most browsers completely block their UI during a synchronous ajax call, it doesn't get around to it until later.
Obviously, wherever possible, just don't use synchronous ajax, since it has this behavior of blocking the UI.
But, if you absolutely cannot avoid making it synchronous (I've never encountered a valid example of such a situation; I'm told they exist), add a brief delay after jQuery thinks the animation is done before starting your ajax. Firefox in particular seems to want a fair bit of time:
$("#ajax-loader").show(1, function(){
setTimeout(function() {
$.ajax({
url: xxx,
type: "POST",
async: false,
success: function (data) {
hideAjaxLoader();
}
});
}, 50); // 50 ms
});
Again, I strongly recommend not using synchronous ajax, but if you need to, just delay the onset.
I put a sleep(5) in ajax.php page. I need the code returned to start another function group. It is also using ajax. My first ajax call looks like this:
$.ajax({
url: '/ajax.php',
data: {
id : code
} ,
type: 'POST',
async:false, //<<< here
cache: false,
beforeSend: function(){
$('#loading').dialog();
},
success: function(data){
console.log(data.result);
$('#loading').dialog('close');
initAnotherFunctionGrop(data.result);
},
error: function(){
$('#loading').dialog('close');
}
});
Why I cannot show to the loading message in IE and Chrome? Just Firefox is working with that.
Asynchronous code is best. Synchronous code can hang your browser, which makes it a bad idea in the case of ajax, where the speed of the ajax request depends on factors beyond the users computer and the browser. You don't want the users machine to hang, so avoid it. Instead try something like this.
function a(passedData){
return $.ajax({
url : '/ajax.php',
data : passedData
});
}
function b(passedData){
return $.ajax({
url : '/ajaxB.php',
data : passedData
});
}
$.when(a(data),b(data)).then(function(successDataForA,successDataForB){
//Do code after all asynchronous ajax calls are done.
//As a whole this is still asynchronous so other things can still run
},function(failA,failB){
//This fail callback is not necessary but here it is if needed
});
Use this
$(document).ready(function () {
$('#ajaxloading').hide() // hide it initially
.ajaxStart(function () {
$(this).show();
})
.ajaxStop(function () {
$(this).hide();
});
});
here "ajaxloading" is the Id of the DIV, which you want to display or hide. U can put any content inside this div
If your loading image is gif image, then its hard to show it in IE and chrome, as these browsers stop any changes to DOM component while synchronous call and once the code is executed it shows all the changes.
You can test it by putting an alert box just after you load an image.
$('#loading').dialog();
alert('loading image');
Once alert it popup, you can now see loading image in both IE and chrome as alert stop thread execution until a response is given by user.
Read this link:
[https://stackoverflow.com/questions/11946828/loading-gif-image-is-not-showing-in-ie-and-chrome]
I've had problems in the past getting IE to show a "loading..." message during an Ajax call even with an async call (which is what I'd certainly recommend you use), where the same code did work in FF.
The workaround that has worked for me with IE (and done no harm in FF) is to do something like this:
$('#loading').dialog();
setTimeout(function() {
$.ajax(...);
},1);
That is, show the "loading" message then postpone the Ajax call by use of setTimeout() - this gives the browser a moment to redraw the page after the current JS finishes but before the timeout kicks in.
But of course if you're doing a synchronous request you presumably have additional code that you want to run after the $.ajax() method using its results, so you'd need to move all of that into the function you pass to setTimeout() (or call it from there, anyway).
This code hangs.
I am reasonably sure it's because the response in the anonymous function is a new variable not connected with the outer scope. How do I solve this?
function foo() { //...
var url = "http://urliciously-urlish-url"
response = null;
$.get(url, function (data) {response = data;
});
while( response === null)
{
1;
}
console.log(response);
//...
}
Note I am aware that this design will (as usual for polling systems) hang the page until response becomes non-null. That's OK in this context.
$.get is asynchronous. If you really want this to be synchronous, you'll have to use the $.ajax function:
$.ajax({
url: url,
async: false,
success: function(data) {
response = data;
}
});
That being said, I agree with cHao -- you should get used to writing asynchronous code.
While your code is running, the event handlers won't.
Translation: This code won't work.
If you want to use JS, you'll almost definitely have to get used to writing asynchronous code.
No, the problem is that the callback will never be executed because the JS thread is still running. It will wait for the current context to be ended, before it goes on executing the "next tick" (the callback here). Between the ticks it may also update DOM and handle other things.
Instead of using a hanging loop, use a synchronous ajax request (yes, thats possible). In jQuery: {async:false}. However, it then will "only" hang until the request is ended - which maybe never happens. And unresponsable GUI is the worst thing to happen, so DO NOT USE it.
I have a function called:
function callAjax(url, data) {
$.ajax(
{
url: url, // same domain
data: data,
cache: false,
async: false, // use sync results
beforeSend: function() {
// show loading indicator
},
success: function() {
// remove loading indicator
}
}
);
}
In the code, I call "callAjax" X number of times and I want to update the data synchronously. It is done as expected, but one problem: the loading item doesn't show in beforeSend function. If I turn async to true, it works but the updates aren't synchronously done.
I've tried several things with no success. I tried putting the loading indicator before the ajax call like this:
function callAjax(url, data) {
// show loading div
$.ajax(
{
// same as above
}
);
}
But for some reason it doesn't want to show the loading indicator. I notice a strange behavior when I put an "alert" in the beforeSend and the loading indicator appears in that case, but I rather not pop up a message box.
Got any ideas?
Making a synchronous call like that is like putting up an "alert()" box. Some browsers stop what they're doing, completely, until the HTTP response is received.
Thus in your code, after your call to the "$.ajax()" function begins, nothing happens until the response is received, and the next thing as far as your code goes will be the "success" handler.
Generally, unless you're really confident in your server, it's a much better idea to use asynchronous calls. When you do it that way, the browser immediately returns to its work and simply listens in the background for the HTTP response. When the response arrives, your success handler will be invoked.
When you do the blocking I/O the program is halted until the the input is received, in JS words when doing a synchronous call, the program halts and browser window freezes (no painting can be done) until the response is received. In most cases doing syncronus calls and any kind of blocking I/O can be avoided. However imagine your doing a progress bar in java or any other programming language, you have to spawn a different thread to control the progress bar, I think.
One thing to try in your case, is to call the ajax call after a time delay
//loading div stuff,
//if your doing some animation here make sure to have Sufficient
//time for it. If its just a regular show then use a time delay of 100-200
setTimeout( ajaxCall, 500 );
EDIT ajaxcall in setTimeout, Example
This is what you are looking for - .ajaxStart()
It will be triggered when any ajax event starts
http://api.jquery.com/ajaxStart/
They even give a specific example similar to what you are trying to accomplish:
$("#loading").ajaxStart(function(){
$(this).show();
});
You can then use the .ajaxStop() function
$("#loading").ajaxStop(function(){
$(this).hide();
});