Ajax synchronous with jQuery. Is it possible? - javascript

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).

Related

Spinner button that starts spinning when function is called and stops when it ends

I'm trying to make a spinner button that will spin while I make an AJAX request and stop when the answer is received.
I've got the AJAX handled but the spinning doesn't seem to work with the following code:
function refresh (id){
var iconElem = document.getElementById("spinner" + id);
iconElem.classList.add('fa-spin');
sleep(5000);
var buttonRefresh = document.getElementById("refreshButton" + id);
buttonRefresh.classList.remove("fa-spin");
};
Note : I have replaced the ajax function with a sleep (implemented elsewhere, but it works like like it should) since I am in a non-php environment.
What happens here is that the the class "fa-spin" is being added while the sleep is over, even though it comes after in the code... Am I missing some kind of "refresh" that I need to execute in order to make the added class effective ?
You need to stop the spinning in the completion callback of the ajax call as it is a async call.
What you are doing here is starting and then immediately stopping the spinner before the ajax call even finishes.
$.ajax({
url: "test.html",
cache: false,
success: function(html){
// stop the spinner here
}
});
Here is the simplest solution with a callback:
function sleep(callback,timeout){
setTimeout(callback,timeout)
}
sleep(() => {
//stop spinner here
},200)
Anyways, I suggest you to read more here
If you are doing an ajax request, you can also use the async:false header to make your request synced, and then your code should work.
Changes to the style or content of the document become effective only when the JavaScript function finishes and returns to the main event loop. Therefore, assuming your sleep() function works as expected (by doing a busy wait or something like that, although that is not actually sleeping), you can only see the total effect of all changes when the function returns. If you follow the advice of the other answers and remove the style in the callback of the AJAX call, you will be fine.

Won't show loading until ajax finish [duplicate]

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);
})

jQuery ajax/post request with a change of page not working

Now the problem below happens only with Safari. Chrome, Opera, IE all work fine.
I have tried:
function do(x){
$.ajax({url: "next.php",
type: "POST",
data: {'cand': x},
success: leave()});
}
function leave(){window.location = "next.php";}
This:
$.post("next.php", {'cand': x});
window.location = "next.php";
And the other two combinations of the above as well. I noticed that when I don't leave the page, the ajax/post request both work, but when I leave the page, they dont. What I mean is when I use the window.location command. As in, the user will leave the page but the post request will not work. Again, this only happens in Safari. I dont't have a Safari browser immediately in front of me so I cannot test it thoroughly.
Can anyone who has any clue let me know what's going on?
If you do this: success: leave() (as in your first example) then you evaluate leave function immediately, and the change of location occurs concurrently to the ajax call. Some browsers will complete the ajax call, some won't.
Instead, do this: success: leave. This will call leave function after the ajax call.
You could try the following, because here the function() is only called after the PHP execution is completed. In your case, it could be that the callback is executed before the Ajax is completed. In that case you could maybe use a little work around and use setTimeout() to wait a short time before leaving.
$.post('next.php', {cand: x}, function() {
// Callback function: called after php script is completed
// setTimeout waits 500ms before leaving
setTimeout(function(){
leave();
}, 500);
})

$(window).unload not working as expected

I'm making a small chat application with PHP + MySQL + JavaScript, I've written a function disonnectUser(), which is called when the user press the disconnect button. Here it is:
function disconnectUser(){
$.post('web/WEB-INF/classes/handleChatUser.php',{ action: 'disconnect',nick: localNickname});
$('#chat').stop(true,true).fadeOut(2000,function(){
nicknameDialog();
});
$('#messageInput').val(null);
$('#clientList').html(null);
$('#chatScreen').html(null);
clearInterval(refreshIntervalId);
clearInterval(refreshIntervalId2);
connected = false;
}
And it works like a charm, but when I call this very function in another context, when the user instead of pressing disconnect just exit the page, in this function
$(window).unload(function() {
if(connected){
disconnectUser();
connected = false;
}
});
it doesn't work. And I'm sure it's being called, because if I put an alert it's called normally before closing the page. I think the page is closing before the code runs completely, so I think if I put some block there until the code finish running it would work?
The problem is that $(window).unload() doesn't waits any AJAX call before closing the window (what is right because AJAX is assync).
You need to force the AJAX to be sync, ie, wait the response. Inside your disconnectUser function:
$.ajax({
type: 'POST',
async: false, // This is the guy.
url: '/blablabla'
});
You can read more about it here: $(window).unload wait for AJAX call to finish before leaving a webpage
Instead of unload, how about beforeunload?
window.onbeforeunload = function() {
if(connected){
disconnectUser();
connected = false;
}
};
Also, your disconnectUser method already sets connected to false, no need to do it here also.
It also seems that jQuery doesn't really handle the beforeunload event, which is why you'll need to revert to native JS to handle this:
http://groups.google.com/group/jquery-en/browse_thread/thread/4e5b25fa1ff5e5ee?pli=1
Try using a synchronous request. Perhaps in combination with onbeforunload like the other poster suggested. If that doesn't work, I suppose you're out of luck. A request that is synchronous blocks the browser while it's happening, so you might want to use it only for the unload function, assuming the method even works.
function disconnectUser(){
jQuery.ajax({
url: 'web/WEB-INF/classes/handleChatUser.php',
data: { action: 'disconnect',nick: localNickname},
type: 'POST',
async: false
});
$('#chat').stop(true,true).fadeOut(2000,function(){
nicknameDialog();
});
$('#messageInput').val(null);
$('#clientList').html(null);
$('#chatScreen').html(null);
clearInterval(refreshIntervalId);
clearInterval(refreshIntervalId2);
connected = false;
}

jquery ajax synchronous call beforeSend

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();
});

Categories