This question already has answers here:
JavaScript, browsers, window close - send an AJAX request or run a script on window closing
(9 answers)
Closed 6 years ago.
So supposedly starting at Firefox > 4, binding the window jQuery object to beforeunload doesn't work anymore.
What'd I'd like to do is submit an AJAX post to delete my server's memcache data.
When I refresh the only open tab, I can see that the beforeunload event is called in both firefox and chrome with the following code as evidenced by the console.log message, "firefox/NON-firefox delete". The problem is that I never see the console.log message "memcache delete" indicating that my server never saw the $.ajax request.
I realize it is bad to do browser sniffing and that there is no difference between what's included in the if and else statements. I'm merely showing code for what I've tried unsuccessfully in Firefox.
Anyone have any ideas?
$(window).bind('beforeunload', function(){
if(/Firefox[\/\s](\d+)/.test(navigator.userAgent) && new Number(RegExp.$1) >= 4) {
console.log('firefox delete');
memcacheDelete();
return null;
}
else {
console.log('NON-firefox delete');
memcacheDelete();
return null;
}
});
function memcacheDelete() {
$.ajax({
url: "/memcache/delete",
type: "post",
data:{},
success:function(){
console.log('memcache deleted');
}//success
}); //ajax
}
Ajax is asynchronous.
When you refresh (or close)your browser, beforeunload is being called. And it means as soon as beforeunload is finished executing, page will refresh (or close).
When you do an ajax request, (since its asynchronous) javascript interpreter does not wait for ajax success event to be executed and moves down finishing the execution of beforeunload.
success of ajax is supposed to be called after few secs, but you dont see it as page has been refreshed / closed.
Side note:
.success() method is deprecated and is replaced by the .done() method
Reference
Just for sake of completion, here's what I did, thanks to #Jashwant for the guidance:
I noticed that this other SO Q&A suggested the same solution.
The KEY is the async:true(false) in the $.ajax call below:
$(window).bind('beforeunload', function(){
if(/Firefox[\/\s](\d+)/.test(navigator.userAgent) && new Number(RegExp.$1) >= 4) {
console.log('firefox delete');
var data={async:false};
memcacheDelete(data);
return null;
}
else {
console.log('NON-firefox delete');
var data={async:true};
memcacheDelete(data);
return null;
}
});
function memcacheDelete(data) {
$.ajax({
url: "/memcache/delete",
type: "post",
data:{},
async:data.async,
success:function(){
console.log('memcache deleted');
}//success
}); //ajax
}
Related
I am currently developing a chat using your typical everyday web programming languages (JavaScript, PHP etc..). The chat is currently fully functional. However, there are several issues that I have yet to solve successfully. One of which being a cross-browser issue.
I am trying to run an AJAX request when a user closes the tab. The PHP for this request looks something like this:
date_default_timezone_set("America/New_York");
session_start();
unset($_SESSION["onpage"]);
if ($_POST['logout'] == "false") {
sleep(5);
if (isset($_SESSION["onpage"]) || !empty($_SESSION["onpage"])) die();
}
...
...
And the AJAX being:
$.ajax({ // this is jQuery
type: "POST",
url: "offline.php",
data: {
logout: out ? 'true' : 'false'
},
success: function (data) {
document.location.reload();
}
});
Basically, when a user closes the tab (in that case $_POST['logout'] will equal false), the request should not finish until the 5 seconds (sleep(5)) have finished. This is because I do not want this request to be fired when a user simply refreshes the page, only when it is confirmed that he left the page.
This is where the cross-browser issue comes in. The functionality I want to achieve works perfectly fine in Safari. This being that on refresh, the request doesn't finish, but if I close the tab, after 5 seconds it does what it is suppose to do and completes. However, on chrome when I hit refresh, refresh itself does not complete until the 5 seconds are over already over which means the request completes regardless. Chrome is waiting for the AJAX to be completed while Safari does not.
Is there any simply fix to this issue?
Edit:
I have tried the following code from a suggestion in the comments:
var isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);
if (isChrome) {
var formData = new FormData();
formData.append("logout", "false");
navigator.sendBeacon("offline.php", formData);
} else {
$.ajax({ // this is jQuery
type: "POST",
url: "offline.php",
data: {
logout: 'false'
},
success: function (data) {
document.location.reload();
}
});
}
It however did not successfully work.
This question already has an answer here:
Run function if jQuery.ajax waiting for respond long enough
(1 answer)
Closed 8 years ago.
I know about the timeout setting for the ajax call. But what i'm wondering is, is there a way to display a message to the user if an ajax call is still processing but taking longer than x seconds.
E.g.
During an ajax call, if it takes longer than 10 secs tell the user, "call taking longer than expected"
I'd say your best bet is to use window.setTimeout for however long you want to wait for before showing your notification, and then add a window.clearTimeout line to your success callback in your $.ajax() call:
var loadingTimeout = window.setTimeout(function() {
// show your warning here
alert('Still loading :P');
}, 10000); // 10000ms = 10sec
$.ajax({
url: 'http://your/url/here',
dataType: 'json',
type: 'GET',
success: function(r) {
window.clearTimeout(loadingTimeout);
// your results logic here
}
})
Sure, just setTimeout() yourself another function that checks some global variable that gets set by the ajax completion callback. In that function, if the ajax call is still outstanding, show a message.
This question already has answers here:
Abort Ajax requests using jQuery
(18 answers)
Closed 8 years ago.
I would like to stop an ajax call in jquery, which is not working
var xhr = null;
xhr = $.ajax({
url : 'www.example.com?some-large-call',
success : function(responseText) {
// some DOM manipulation
}
});
$("#button").click(function() { xhr.abort() });
I referred the below link
http://www.stoimen.com/blog/2009/09/29/jquery-stop-an-ajax-call/
this probally has more XHR..
Please see this answer:
jquery abort() ajax request before sending another
From the link:
every time you do ajax request, add to array:
requests.push(
$.ajax({
type: 'post',
url: '/test.php',
data: search_data,
success: function(data) {
$('#catalog').html(data);
}
}));
Then, when you want to stop calls..
loop through array and abort all calls..
for(var i = 0; i < requests.length; i++)
requests[i].abort();
Thanks
xhr.abort() it will cause the client to stop listening for the event, but probably it may not stop the server from processing it.
Provided the code you've pasted is the code you're actually using it's no wonder it doesn't work.
As it states on the site it is just pseudo code to illustrate an example. There is no AJAX request there and nothing to stop (at least nothing large enough to be able to stop)
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am using following JS code to call a web handler.
This code calls the handler perfectly JUST IN IE and not FF.
$.ajax({ type: "GET",
url: "../MasterPages/AHMHandler.ashx?T=1",
dataType: "HTML",
success: function (msg) {
document.getElementsByName('cartId')[0].value = msg;
}
,
error: function (e) {
return false;
}
});
Sleep(2000);
What is the problem with my code?
Having seen the Sleep() call in your code, and your comment about alert(), I would say that your problem is with a lack of understanding of how Ajax code works.
When you mak an Ajax call, it is called asynchronously. This means that the call is made, and then the rest of your current function carries on running without stopping to wait for the ajax code to run.
The ajax success function will be called eventually, but only when the http request is complete. In the meanwhile, your current function will carry on running.
The point here is that you cannot rely on a given sequence of events if you have code in the same function that runs after the ajax call is made.
Putting a Sleep() there might make it appear to work because some browsers might see the sleeping time as an opportunity to run the ajax success function, so your code seems to run in the right order. Putting an alert() there will be even more likely to make it work, because the alert() will generally take more time before it is cleared, so the ajax function has more chance to run.
But you should not rely on either of them to get your execution sequence right.
What you should do instead is put the code that you want to run after the ajax call inside the success function. This is the only way to be sure that it will be run after the ajax call is finished.
Hope that helps.
[EDIT] Further clarification after OP's comment:
Spudley, Sleep Function is my own function to keep browser from being redirect for like 2 secs. function Sleep(milliseconds) { var start = new Date().getTime(); for (var i = 0; i < 1e7; i++) { if ((new Date().getTime() - start) > milliseconds) { break; } } }
Just for ref, a sleep function like that is a really terrible idea in Javascript. You should use a setTimeout() for that kind of thing.
However, the point is still the same -- you have code that runs after the $.ajax(), and it will be blocking execution of your ajax success function. If you're doing a redirect right afterward, then the success function probably never gets a chance to run.
An alert() would indeed make it work that because the success function will find a slot to run when the alert is cleared, before Sleep is called, but you shouldn't rely on that.
The answer remains the same: You should put the code that you want to run after the ajax call inside the success function.
Here's a your code with the changes made:
$.ajax({ type: "GET",
url: "../MasterPages/AHMHandler.ashx?T=1",
dataType: "HTML",
success: function (msg) {
document.getElementsByName('cartId')[0].value = msg;
setTimeout(function() { //this instead of your Sleep function
//this is where you need to do your redirect, or whatever else you're doing after the ajax completes.
}, 2000);
}
,
error: function (e) {
return false;
}
});
//don't put **any** code here after the ajax call! put it in the success function.
I have tested this on Firefox, Opera and Seamonkey. It works fine. When it comes to Internet Explorer 7. It works but upto a certain point. I am making an AJAX call to a PHP script every few seconds. In IE7 it makes the first AJAX call and it retrieves the data but it doesn't do it again ever. Even though i have a setTimeout function in the else block. WHY? :(
startTime = setTimeout('getStatus()', 5000);
}//function convertNow
function getStatus()
{
$.ajax({
type: "GET",
url: "fileReader.php",
data: 'textFile=' + fileNameTxt,
success: function(respomse){
textFileResponse = respomse.split(" ");
$("#done").html("Downloading & Converting Video...<b style='font-size:17px;color:green;'>" + textFileResponse[0] + "</b><br /><b>" + properFileName + '</b>');
}
});//ajax
if(textFileResponse[0]=='100.0%'){
}
else{
continueTime = setTimeout('getStatus();', 3000);
alert('call end');
}
}
Apologies if any frustration comes through this question. I've been running around like a headless chicken for the past 3 hours.
Thank you for any help.
EDIT 2
I have added the full function. The setTimeout seems to be working correctly. It must be the AJAX call, am just checking what is being returned. Even stranger! It keeps returning the same value from the AJAX request and its not getting any newer values!! I think Answer 2 might have something.It may be due with cache but how do you over come that?
Are you requesting the ajax call via HTTP GET as opposed to HTTP POST? IE tends to use cached results of ajax calls unless you use POST instead of GET.
EDIT: Since you've updated your question, I can see that you are indeed using the GET verb. Change it to POST and I bet your issue will be resolved.
You could still use the GET request and simply add
cache: false
to the $.ajax request.
Not at all sure on this but are you missing the ;?
from:
setTimeout('getStatus()', 3000);
to:
setTimeout('getStatus();', 3000);
I noticed that textFileResponse is set in the function declaration of the success handler for the AJAX call yet referenced as an array immediately after making the AJAX call. Perhaps in IE 7 the success handler hasn't completed before the array reference which would throw a java script error, thus the setTimeout would never run.