I have created a long polling using jQuery / PHP. and it is working perfectly. The issue is when a user click on other links or refresh the current page, it will hang on the current page till it get response from last AJAX request from server.
I have set about 30 sec in the server side to pick the latest data, means if someone sent a request to get the latest data, he cannot go to another page or refresh the current page till it returns the response. The worse case is, if the server didnt find the latest data, it will send the response after 30 sec.
I have use the following code to abort the request.
window.onbeforeunload = function(event) {
xhr.abort();
}
I have check on the console before and after execute xhr.abort() it shows readyState=1 and then readyState=0. Does this means xhr.abort() executed successfully? But why still the page hang on the current page till it returns the response.
Please help me to solve my issue. I don't want to wait until the server response when user click on other link or refresh page or do other stuff on the page.
This is my jQuery code
function setNoti(ntotal)
{
var t;
xhr = $.ajax({
type: "POST", url: myURL, data: "", dataType: "JSON", cache: false, async: true,
success: function(data) {
// do my work here
clearInterval(t);
t = setTimeout(function() {
setNoti(20);
}, 1000);
return false;
},
error: function()
{
clearInterval(t);
t = setTimeout(function() {
setNoti(0);
}, 40000);
return false;
}
});
}
You are assigning an xhr which can then be used to abort the request on subsequent calls to the function.
function setNoti(ntotal)
{
if (xhr) {
xhr.abort();
}
var t;
xhr = $.ajax({
type: "POST", url: myURL, data: "", dataType: "JSON", cache: false, async: true,
success: function(data) {
// do my work here
clearInterval(t);
t = setTimeout(function() {
setNoti(20);
}, 1000);
return false;
},
error: function()
{
clearInterval(t);
t = setTimeout(function() {
setNoti(0);
}, 40000);
return false;
}
});
}
No need for the window.onbeforeunload handler, which being a separate event is likely being called at the wrong time.
I have added session_write_close() in the server side and it is working perfectly. Following post helped me to find the solution :)
Multiple AJAX requests delay each other
Related
Here's my code:
$.ajax( {
type: "POST",
url: "/script.php",
data: { "action" : "importData" },
cache: false,
async: true,
success: function() {
window.location.href = "/next-page";
}
} );
When a user lands on this page, ajax will trigger the php script which takes about 15 seconds to complete. Rather than having the user wait for the script to complete and then redirect them, I want to get some type of confirmation that the script has been triggered, then redirect the user without waiting for the entire script to complete. The results of the script isnt used until many minutes later in the workflow.
Is this possible? How to do so?
$.ajax() returns the XMLHttpRequest instance:
var xhr = $.ajax({
type: 'POST',
url: '/script.php',
data: {action: 'importData'},
cache: false,
success: function(){
location = '/next-page';
}
});
/* to test if problem is jQuery remove this line and take comments out
var px = xhr.onreadystatechange;
*/
xhr.onreadystatechange = function(){
//if(px)px();
if(xhr.readyState === 3 && xhr.status === 200){ // look at Properties -> https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
// do stuff here with xhr.readyState less than 4
}
}
Valid XMLHttpRequest.readyState property values can be found here.
Note that if you redirect the user, JavaScript on the current page stops. The page that your user is redirected to may have it's own JavaScript.
Here is my code for loading data
$(document).ready(function() {
$.get('get-answers.php', {
project_question_id: <?=$project_question_id?>,
project_id: <?=$project_id?>
}, function(data) {
$('#dispaly-answers').append(data);
});
});
This code retrieves data from database and working fine. But problem here is that if I add new data on the database, this data doesn't show up without page refresh.
So I don’t want to refresh the page to get the data. It should be displayed once new data added to database.
Any suggestions on this issue?
P.S : I also tried .ajax(), didn’t work.
Here is my $.ajax() request
$(document).ready(function() {
$.ajax( {
type: "GET",
url: "get-answers.php",
data: { project_question_id: <?=$project_question_id?>,
project_id: <?=$project_id?>
},
cache: false,
success: function(data) {
$('#dispaly-answers').append(data);
},// success
})// ajax
});
Does the same as $.get()
If your goal is to refresh the page data without refreshing the page, you can put your code in an interval timer and let it auto refresh every x seconds, like below.
setInterval(getAnswer(), 1000);
note: setInterval fires again and again until you clear it, while setTimeout only fires once.
The Ajax-Function get only called once: In the moment the document is ready (fully loaded). You have to use setTimeout to create a timer, which calls the function every minute or whatever you want. Like this:
function getData() {
setTimeout(function(){
$.get('get-answers.php', {
project_question_id: <?=$project_question_id?>,
project_id: <?=$project_id?>
}, function(data) {
$('#dispaly-answers').append(data);
getData();
});
}, 3000);
}
Here is my final approach
$(document).ready(function() {
setInterval(function(){
$.ajax( {
type: "GET",
url: "get-answers.php",
data: { project_question_id: <?=$project_question_id?>,
project_id: <?=$project_id?>
},
cache: false,
success: function(data) {
$('#dispaly-answers').html(data);
},// success
})// ajax
}, 1000);
});
Without creating and calling function getData(), this code working fine. Also I have changed .append(data) to .html(data).
But still I'm not happy with my code because it is constantly retrieving data from database that makes data server busy.
Whatever I wanted to tasks has to be done and it is done.
Try this you just need to replace this file retrieve_query.php and this id query-div with yours.
setInterval(function(){
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
$('#query-div').html(this.responseText);
}
};
xmlhttp.open("GET","retrieve_query.php",true);
xmlhttp.send();
},1000);
I am trying to display a loading animation and hide the search input box before the ajax request has been sent, the ".se-pre-con" element is the loader.
As you can see below I am tring to show this in the beforeSend of the ajax request. However, when the user is typing in the search box then stops for the delay specified (1000ms) the input box still displays throughout the ajax request but it is unresponsive.
Then the results are returned, and the loading animation does the fadeOut so it the show() must be triggering but the page remains unchanged until the results are returned. I want to prevent the unresponsive page effect and show a loading animation during the request. Any help is much appreciated.
$(document).ready(function() {
var delay = (function() {
var timer = 0;
return function(callback, ms) {
clearTimeout(timer);
timer = setTimeout(callback, ms);
};
})();
$('#search_field').keyup(function() {
var target = $(this);
delay(function() {
getSearchResults(target.val());
}, 1000);
});
function getSearchResults(str) {
$.ajax({
beforeSend: function(){
$(".se-pre-con").show();
$("#search_field").hide();
},
url: "http://example.com/Search_Results.php",
dataType:"html",
data: {"search_term": str},
method: "post",
async: false,
success: function(data){
if(data !== null) {
$("#search_default").hide();
$("#search_results_wrapper").html(data);
}
$(".se-pre-con").fadeOut("slow");
$("#search_field").show();
$("#search_field").focus();
},
error: function(){
$(".se-pre-con").fadeOut("slow");
$("#search_field").show();
$("#search_field").focus();
}
});
}
});
I found the solution.
Solution
It started working when I removed the option:
async: false
I'm having trouble with lag and script execution.
I have the following code:
$(function(){
$("#results").html("Loading work order queue...");
setInterval("showWorkOrders();", 15000)
});
function showWorkOrders()
{
$.ajax({
url: '/ajax/job_queue_ajax.php',
type: 'POST',
cache: false,
data: 'update=true',
success: function(data)
{
$("#results").html(data);
$('span#ref_msg').html('');
},
error: function()
{
a = new customModal('ajax');
$("#results").html("<font class='msgDivError'>"+a.ajaxError+"</font>");
$('span#ref_msg').html('');
}
});
}
My backend PHP (only an example):
$SQL = MySQL_query("SELECT * FROM table")
while($data = MySQL_fetch_array($SQL))
{
//// OUTPUTS A TABLE WITH INFORMATION
}
Now, this whole thing executes however with a lot of lag (takes very long to load) and sometimes creates an script error because it took too long to load. If I extend the refresh interval, things start getting better (the lag remains) and I don't get the execution error. I need to have a short interval for what I need, but I cannot figure out an efficient way of doing so. Any suggestions on how to improve this?
Also, after a while of being on the page that has the refresher, the browser becomes extremely slow to the point where it locks...
I would solve it using setTimeout instead:
$(function(){
$("#results").html("Loading work order queue...");
showWorkOrders();
});
function showWorkOrders()
{
$.ajax({
url: '/ajax/job_queue_ajax.php',
type: 'POST',
cache: false,
data: 'update=true',
success: function(data)
{
$("#results").html(data);
$('span#ref_msg').html('');
setTimeout("showWorkOrders();", 5000)
},
error: function()
{
a = new customModal('ajax');
$("#results").html("<font class='msgDivError'>"+a.ajaxError+"</font>");
$('span#ref_msg').html('');
setTimeout("showWorkOrders();", 5000)
}
});
}
This would mean that it waits 5s before doing a new ajax request, the previous one can take however long it wants. Still waits 5s before it tries again.
Try this. Start next request only after response from server.
$(function(){
$("#results").html("Loading work order queue...");
showWorkOrders();
});
function showWorkOrders()
{
$.ajax({
url: '/ajax/job_queue_ajax.php',
type: 'POST',
cache: false,
data: 'update=true',
success: function(data)
{
$("#results").html(data);
$('span#ref_msg').html('');
setTimeout(showWorkOrders, 15000);
},
error: function()
{
a = new customModal('ajax');
$("#results").html("<font class='msgDivError'>"+a.ajaxError+"</font>");
$('span#ref_msg').html('');
setTimeout(showWorkOrders, 15000)
}
});
}
Instead of Ajax on interval, I'd suggest next Ajax after completion.
Since the ajax request takes an indeterminate amount of time to complete, I would suggest that you trigger the next ajax request when the first one completes using setTimeout() and so on like this so that you never have multiple ajax requests going at once and so each subsequent ajax call starts a known time from when the previous one completed.
You probably want to troubleshoot why your server is taking so long to respond to the request, but you can also extend the timeout for the ajax call if your server sometimes takes a long time to respond:
function showWorkOrders()
{
$.ajax({
timeout: 15000,
url: '/ajax/job_queue_ajax.php',
type: 'POST',
cache: false,
data: 'update=true',
success: function(data)
{
$("#results").html(data);
$('span#ref_msg').html('');
setTimeout(showWorkOrders, 5000);
},
error: function()
{
a = new customModal('ajax');
$("#results").html("<font class='msgDivError'>"+a.ajaxError+"</font>");
$('span#ref_msg').html('');
setTimeout(showWorkOrders, 5000);
}
});
}
$(function(){
$("#results").html("Loading work order queue...");
showWorkOrders();
});
I've posted a question about it already, but I've figured out what is the exact problem. Now, I need a solution for that :)
Here's my code:
$('input[type="text"][name="appLink"]').unbind('keyup').unbind('ajax').keyup(function() {
var iTunesURL = $(this).val();
var iTunesAppID = $('input[name="iTunesAppID"]').val();
$.ajax({
type: 'POST',
url: jsonURL,
dataType: 'json',
cache: false,
timeout: 20000,
data: { a: 'checkiTunesURL', iTunesURL: iTunesURL, iTunesAppID: iTunesAppID },
success: function(data) {
if (!data.error) {
$('section.submit').fadeOut('slow');
//Modifying Submit Page
setTimeout(function() {
$('input[name="appLink"]').val(data.trackViewUrl);
$('div.appimage > img').attr('src', data.artworkUrl512).attr('alt', data.trackName);
$('div.title > p:nth-child(1)').html(data.trackName);
$('div.title > p:nth-child(2)').html('by '+data.sellerName);
$('span.mod-category').html(data.primaryGenreName);
$('span.mod-size').html(data.fileSizeBytes);
$('span.mod-update').html(data.lastUpdate);
$('select[name="version"]').html(data.verSelect);
$('input[name="iTunesAppID"]').attr('value', data.trackId);
}, 600);
//Showing Submit Page
$('section.submit').delay('600').fadeIn('slow');
} else {
$('.json-response').html(data.message).fadeIn('slow');
}
},
error: function(jqXHR, textStatus, errorThrown) {
//$('.json-response').html('Probléma történt! Kérlek próbáld újra később! (HTTP Error: '+errorThrown+' | Error Message: '+textStatus+')').fadeIn('slow');
$('.json-response').html('Something went wrong! Please check your network connection!').fadeIn('slow');
}
});
});
The Problem and Explanation:
Every time a key is triggered up it loads this ajax. If my JSON file finds a keyword it returns with error = false flag. You see, if it happens, it loads the effects, changing, etc...
The problem is that when you start to type, for example asdasdasd and just after that I paste / write the keyword there'll be some ajax queries which ones are still processing. These ones are modifying and loading the fadeOut-In effects X times.
So I'd need a solution to stop the processing ajax requests, while an other key is pressed!
Thanks in advance,
Marcell
Personally I would have the script wait so it didn't fire on each keyup. Actually I would probably use http://jqueryui.com/autocomplete/
But you can just abort the ajax before trying again.
...
var iTunesAppID = $('input[name="iTunesAppID"]').val();
if (typeof req!='undefined' && req!=null) req.abort();
req = $.ajax({
...
try adding the option async: false to your ajax this will prevent any other calls until the current one is finished.