javascript does not reconnect to server side if connection is lost - javascript

I have Jquery+Ajax page that connects to server gets some data, and displays it. This is done all the time, function calls itself after it completes all task and starts to perform again and again. But If komputer loses internet connection everything stops. And when connections comes back again, nothing happens. Here is javascript code. How can I iprove it so it will continue to work after connection is back again.
$(document).ready(function() {
var a=1;
var max='23';
function kiosk()
{
if(a<max)
{
$.post('engine.php', { index: a },
function(result)
{
result = jQuery.parseJSON(result);
$('#main').css({'display':'none'});
$('#div_city').html(result.dest);
$('#div_price').html(result.price);
$('#div_price_pre').html('From ');
$('#div_price_after').html(' Euro');
$('#main').fadeIn(2000).delay(3000).fadeOut(2000, function()
{
$('#main').hide;
a++;
kiosk();
});
});
}
else
{
a=1;
kiosk();
}
}
kiosk();
});

I would suggest rather than using $.post you use
$.ajax({ type: "post" , success : function1() , failure: function2() }.
In function2() you can call koisk again after a timeout. and the succces would be the function you have created right now.
This link will help you understand the ajax function jQuery Ajax error handling, show custom exception messages
Eg Code snippet:
function kiosk()
{
if(a<max)
{
$.ajax({type : "POST" , url : 'engine.php',data: { index: a },
success : function(result)
{
result = jQuery.parseJSON(result);
$('#main').css({'display':'none'});
$('#div_city').html(result.dest);
$('#div_price').html(result.price);
$('#div_price_pre').html('From ');
$('#div_price_after').html(' Euro');
$('#main').fadeIn(2000).delay(3000).fadeOut(2000, function()
{
$('#main').hide;
a++;
kiosk();
});
},error : function (xhr, ajaxOptions, thrownError){ setTimeout(200,kiosk()) }
});
}
else
{
a=1;
kiosk();
}
}
kiosk();
});`

Using jQuery.post you are passing a callback which is executed only on success.
You should use jQuery.ajax which has different callbacks. See documentation with complete, success and error callbacks.
You could even use statusCode to map a specific HTTP code to a custom function.

Script brokes because i think it throws exception. You can add your code try and catch block, and even if has errors you can continue to try.
try {
result = jQuery.parseJSON(result);
// do your work
} catch {
// call function again
}
Or you can use, jquery ajax, it has a onerror event.

Related

How to make repeated ajax calls and abort all the previous calls which is not finished yet when it enters some particular function?

This is my ajax function
function repeatedCall() {
$.ajax({
url: '/getUrl',
complete: function(data) {
if (data.statusText != "error") {
//my actions
}
}
})
}
setInterval(repeatedCall, 5000); //To make repeated ajax calls
function updateData_function{
//I want to abort all previous ajax calls and make a new ajax call since it will update the data
}
I can use clearInterval but the pending calls are not getting aborted and hence it is not updating properly.
How can i make repeated calls and at the same time abort all the requests if it enters my updateData_function.
This updateData_function will have new values so i need to make fresh ajax request.
How can i do this? Please help!! Thanks a lot in advance!!
Using setInterval to make repetead calls is not a good practice. Assume that your previous request is not completed, then there is no point in making the same ajax call. Also, as you may know, there are possibility that the response from the previous ajax call can come after the recent ajax response. So it is always better to abort any previous ajax calls.
I think the below solutions may solve your issue:
Solution 1: Just Extentending what you have done:
var xhr
function repeatedCall() {
if(xhr){
// abort any previous calls, to avoid any inconsistency
xhr.abort()
}
xhr = $.ajax({
url: '/getUrl',
complete: function(data) {
if (data.statusText != "error") {
//my actions
}
}
})
}
setInterval(repeatedCall, 5000)
function updateData_function {
//I want to abort all previous ajax calls and make a new ajax call since it will update the data
if(xhr){
xhr.abort()
}
}
Solution 2: What I feel is a better approach
var xhr;
function repeatedCall() {
xhr = $.ajax({
url: '/getUrl',
complete: function(data) {
if (data.statusText != "error") {
//my actions
// Call the ajax call again:
setTimeout(repeatedCall, 5000)
}
}
})
}
function updateData_function {
//I want to abort all previous ajax calls and make a new ajax call since it will update the data
if(xhr){
xhr.abort()
}
// do something
}
// somewhere - to initiate the repeatedCall for the first time
repeatedCall()
I faced the same problem before as well and I was sending to many ajax calls on keyup which was leading my website to collapse. I found out the solution to setTimeout(); in to the ajax all firing and keeping firing the function clears timeout and settimeout again. This let you to fire ajax only 1 time on pressing to many time.
Edit: Ok for example I had a searchbox which was getting predefined suggestions with ajax call with onkeyup function. as I was start typing it was firing ajax call again and again and stucking. I started to cancel the one before as I firing another so fixed the situation. Here is the DEMO Doesnt matter how many time you hit the button it fires only one.
I've modified my code and this works
abortValue = false;
var xhr;
xhrPool = [];
var trying;
function abortAjax() {
$.each(xhrPool, function(idx, jqXHR) {
jqXHR.abort();
});
}
$(document).ready(function() {
fn = function() {
xhr = $.ajax({
url: '/getUrl',
beforeSend: function(jqXHR) {
xhrPool.push(jqXHR);
},
complete: function(jqXHR, data) {
if (abortValue == true) {
abortAjax()
} else {
if (jqXHR.statusText != "error" && "undefined") {
//myactions
}
}
}
});
};
var interval = setInterval(fn, 5000);
});
function updateData_function {
//I want to abort all previous ajax calls and make a new ajax call since it will update the data
abortValue = true;
abortAjax();
abortValue = false;
fn();
}

How Do I Stop a Web Service Method That Has Been Executed [duplicate]

Is it possible that using jQuery, I cancel/abort an Ajax request that I have not yet received the response from?
Most of the jQuery Ajax methods return an XMLHttpRequest (or the equivalent) object, so you can just use abort().
See the documentation:
abort Method (MSDN). Cancels the current HTTP request.
abort() (MDN). If the request has been sent already, this method will abort the request.
var xhr = $.ajax({
type: "POST",
url: "some.php",
data: "name=John&location=Boston",
success: function(msg){
alert( "Data Saved: " + msg );
}
});
//kill the request
xhr.abort()
UPDATE:
As of jQuery 1.5 the returned object is a wrapper for the native XMLHttpRequest object called jqXHR. This object appears to expose all of the native properties and methods so the above example still works. See The jqXHR Object (jQuery API documentation).
UPDATE 2:
As of jQuery 3, the ajax method now returns a promise with extra methods (like abort), so the above code still works, though the object being returned is not an xhr any more. See the 3.0 blog here.
UPDATE 3: xhr.abort() still works on jQuery 3.x. Don't assume the update 2 is correct. More info on jQuery Github repository.
You can't recall the request but you can set a timeout value after which the response will be ignored. See this page for jquery AJAX options. I believe that your error callback will be called if the timeout period is exceeded. There is already a default timeout on every AJAX request.
You can also use the abort() method on the request object but, while it will cause the client to stop listening for the event, it may probably will not stop the server from processing it.
Save the calls you make in an array, then call xhr.abort() on each.
HUGE CAVEAT: You can abort a request, but that's only the client side. The server side could still be processing the request. If you are using something like PHP or ASP with session data, the session data is locked until the ajax has finished. So, to allow the user to continue browsing the website, you have to call session_write_close(). This saves the session and unlocks it so that other pages waiting to continue will proceed. Without this, several pages can be waiting for the lock to be removed.
It's an asynchronous request, meaning once it's sent it's out there.
In case your server is starting a very expensive operation due to the AJAX request, the best you can do is open your server to listen for cancel requests, and send a separate AJAX request notifying the server to stop whatever it's doing.
Otherwise, simply ignore the AJAX response.
AJAX requests may not complete in the order they were started. Instead of aborting, you can choose to ignore all AJAX responses except for the most recent one:
Create a counter
Increment the counter when you initiate AJAX request
Use the current value of counter to "stamp" the request
In the success callback compare the stamp with the counter to check if it was the most recent request
Rough outline of code:
var xhrCount = 0;
function sendXHR() {
// sequence number for the current invocation of function
var seqNumber = ++xhrCount;
$.post("/echo/json/", { delay: Math.floor(Math.random() * 5) }, function() {
// this works because of the way closures work
if (seqNumber === xhrCount) {
console.log("Process the response");
} else {
console.log("Ignore the response");
}
});
}
sendXHR();
sendXHR();
sendXHR();
// AJAX requests complete in any order but only the last
// one will trigger "Process the response" message
Demo on jsFiddle
We just had to work around this problem and tested three different approaches.
does cancel the request as suggested by #meouw
execute all request but only processes the result of the last submit
prevents new requests as long as another one is still pending
var Ajax1 = {
call: function() {
if (typeof this.xhr !== 'undefined')
this.xhr.abort();
this.xhr = $.ajax({
url: 'your/long/running/request/path',
type: 'GET',
success: function(data) {
//process response
}
});
}
};
var Ajax2 = {
counter: 0,
call: function() {
var self = this,
seq = ++this.counter;
$.ajax({
url: 'your/long/running/request/path',
type: 'GET',
success: function(data) {
if (seq === self.counter) {
//process response
}
}
});
}
};
var Ajax3 = {
active: false,
call: function() {
if (this.active === false) {
this.active = true;
var self = this;
$.ajax({
url: 'your/long/running/request/path',
type: 'GET',
success: function(data) {
//process response
},
complete: function() {
self.active = false;
}
});
}
}
};
$(function() {
$('#button').click(function(e) {
Ajax3.call();
});
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="button" type="button" value="click" />
In our case we decided to use approach #3 as it produces less load for the server. But I am not 100% sure if jQuery guarantees the call of the .complete()-method, this could produce a deadlock situation. In our tests we could not reproduce such a situation.
It is always best practice to do something like this.
var $request;
if ($request != null){
$request.abort();
$request = null;
}
$request = $.ajax({
type : "POST", //TODO: Must be changed to POST
url : "yourfile.php",
data : "data"
}).done(function(msg) {
alert(msg);
});
But it is much better if you check an if statement to check whether the ajax request is null or not.
Just call xhr.abort() whether it's jquery ajax object or native XMLHTTPRequest object.
example:
//jQuery ajax
$(document).ready(function(){
var xhr = $.get('/server');
setTimeout(function(){xhr.abort();}, 2000);
});
//native XMLHTTPRequest
var xhr = new XMLHttpRequest();
xhr.open('GET','/server',true);
xhr.send();
setTimeout(function(){xhr.abort();}, 2000);
You can abort any continuous ajax call by using this
<input id="searchbox" name="searchbox" type="text" />
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script type="text/javascript">
var request = null;
$('#searchbox').keyup(function () {
var id = $(this).val();
request = $.ajax({
type: "POST", //TODO: Must be changed to POST
url: "index.php",
data: {'id':id},
success: function () {
},
beforeSend: function () {
if (request !== null) {
request.abort();
}
}
});
});
</script>
As many people on the thread have noted, just because the request is aborted on the client-side, the server will still process the request. This creates unnecessary load on the server because it's doing work that we've quit listening to on the front-end.
The problem I was trying to solve (that others may run in to as well) is that when the user entered information in an input field, I wanted to fire off a request for a Google Instant type of feel.
To avoid firing unnecessary requests and to maintain the snappiness of the front-end, I did the following:
var xhrQueue = [];
var xhrCount = 0;
$('#search_q').keyup(function(){
xhrQueue.push(xhrCount);
setTimeout(function(){
xhrCount = ++xhrCount;
if (xhrCount === xhrQueue.length) {
// Fire Your XHR //
}
}, 150);
});
This will essentially send one request every 150ms (a variable that you can customize for your own needs). If you're having trouble understanding what exactly is happening here, log xhrCount and xhrQueue to the console just before the if block.
I was doing a live search solution and needed to cancel pending requests that may have taken longer than the latest/most current request.
In my case I used something like this:
//On document ready
var ajax_inprocess = false;
$(document).ajaxStart(function() {
ajax_inprocess = true;
});
$(document).ajaxStop(function() {
ajax_inprocess = false;
});
//Snippet from live search function
if (ajax_inprocess == true)
{
request.abort();
}
//Call for new request
Just use ajax.abort() for example you could abort any pending ajax request before sending another one like this
//check for existing ajax request
if(ajax){
ajax.abort();
}
//then you make another ajax request
$.ajax(
//your code here
);
there is no reliable way to do it, and I would not even try it, once the request is on the go; the only way to react reasonably is to ignore the response.
in most cases, it may happen in situations like: a user clicks too often on a button triggering many consecutive XHR, here you have many options, either block the button till XHR is returned, or dont even trigger new XHR while another is running hinting the user to lean back - or discard any pending XHR response but the recent.
The following code shows initiating as well as aborting an Ajax request:
function libAjax(){
var req;
function start(){
req = $.ajax({
url: '1.php',
success: function(data){
console.log(data)
}
});
}
function stop(){
req.abort();
}
return {start:start,stop:stop}
}
var obj = libAjax();
$(".go").click(function(){
obj.start();
})
$(".stop").click(function(){
obj.stop();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="button" class="go" value="GO!" >
<input type="button" class="stop" value="STOP!" >
If xhr.abort(); causes page reload,
Then you can set onreadystatechange before abort to prevent:
// ↓ prevent page reload by abort()
xhr.onreadystatechange = null;
// ↓ may cause page reload
xhr.abort();
I had the problem of polling and once the page was closed the poll continued so in my cause a user would miss an update as a mysql value was being set for the next 50 seconds after page closing, even though I killed the ajax request, I figured away around, using $_SESSION to set a var won't update in the poll its self until its ended and a new one has started, so what I did was set a value in my database as 0 = offpage , while I'm polling I query that row and return false; when it's 0 as querying in polling will get you current values obviously...
I hope this helped
I have shared a demo that demonstrates how to cancel an AJAX request-- if data is not returned from the server within a predefined wait time.
HTML :
<div id="info"></div>
JS CODE:
var isDataReceived= false, waitTime= 1000;
$(function() {
// Ajax request sent.
var xhr= $.ajax({
url: 'http://api.joind.in/v2.1/talks/10889',
data: {
format: 'json'
},
dataType: 'jsonp',
success: function(data) {
isDataReceived= true;
$('#info').text(data.talks[0].talk_title);
},
type: 'GET'
});
// Cancel ajax request if data is not loaded within 1sec.
setTimeout(function(){
if(!isDataReceived)
xhr.abort();
},waitTime);
});
This is my implementation based on many answers above:
var activeRequest = false; //global var
var filters = {...};
apply_filters(filters);
//function triggering the ajax request
function apply_filters(filters){
//prepare data and other functionalities
var data = {};
//limit the ajax calls
if (activeRequest === false){
activeRequest = true;
}else{
//abort if another ajax call is pending
$request.abort();
//just to be sure the ajax didn't complete before and activeRequest it's already false
activeRequest = true;
}
$request = $.ajax({
url : window.location.origin + '/your-url.php',
data: data,
type:'POST',
beforeSend: function(){
$('#ajax-loader-custom').show();
$('#blur-on-loading').addClass('blur');
},
success:function(data_filters){
data_filters = $.parseJSON(data_filters);
if( data_filters.posts ) {
$(document).find('#multiple-products ul.products li:last-child').after(data_filters.posts).fadeIn();
}
else{
return;
}
$('#ajax-loader-custom').fadeOut();
},
complete: function() {
activeRequest = false;
}
});
}

Stop javascript function which is executing all the time

I have multiple JavaScript functions and all of them run at the same time and are running in a loop because I'm reading some data from REST API.
Is there any way to stop execution of those scripts with a button or something?
function termostat1_on_off_get() {
var request = $.ajax({
type: "GET",
url: "http://192.168.1.113:8080/rest/items/termostat1_on_off/state"
});
request.done(function(data) {
console.log("On/off" + data);
if (data == 1) {
termostat1_on_off = "Vklopljen";
$("#m_t1_vklopljen").css('background-color', '#cccccc');
$("#m_t1_izklopljen").css('background-color', '#efefef');
} else {
termostat1_on_off = "Izklopljen";
$("#m_t1_vklopljen").css('background-color', '#efefef');
$("#m_t1_izklopljen").css('background-color', '#cccccc');
}
});
request.fail(function(jqXHR, textStatus) {
console.log( "Failure: " + textStatus );
});
setTimeout(termostat1_on_off_get, 5000);
}
termostat1_on_off_get();
You can use clearTimeout() to stop an in-progress timeout from running. To do this you need to save the id returned from the setTimeout call, then provide it as a parameter to clearTimeout(), like this:
var timeout;
function termostat1_on_off_get()
{
// your ajax logic here...
// inside the callbacks:
timeout = setTimeout(termostat1_on_off_get, 5000);
}
termostat1_on_off_get();
function stopTimeout() {
clearTimeout(timeout);
}
However, you should note that AJAX polling is an anti-pattern which should really be avoided. If you need to keep the UI in sync with the server then you should look in to WebSockets or Server Side Events instead. They perform much better, and save your server from having a meltdown.
Use setInterval instead of setTimeout
var i = 0;
function log() {
console.log(i++);
}
var interval = setInterval(log, 1000);
function stop() {
clearInterval(interval)
};
<button onclick="stop()">Stop</button>

Calling a function until jQuery .post finishes loading

I'm a little new to jQuery framework and while using AJAX with normal javascript I used readyState() function to display a loading gif image. But, I don't know how to use that in jQuery .post() method. Was it possible to add a class until it finishes loading? If so, please give a code sample. My function is similar to this:
$.post("verify.php",{
username: u,
password: p
},function(r) {
if(r == 1) {
$(".elmt").addClass("loading");
} else if (r == 0) {
location.href = 'http://localhost';
}
});
I always prefer using $.ajax for things like this as it has more options than the shortcuts :
$.ajax({
type: 'POST',
url : 'verify.php',
data: {
username: u,
password: p
},
beforeSend: function () {
$(".elmt").addClass("loading"); // add loader
}
}).always(function() { // always executed
$(".elmt").removeClass("loading"); // remove loader
}).done(function(r) { // executed only if successful
if (r == 0) {
location.href = '/';
}
});
Just call the addClass before the $.post() and be done with it
$(".elmt").addClass("loading");
$.post("verify.php", {
username: u,
password: p
}, function (r) {
location.href = 'http://localhost';
});
You could fire a custom event before starting your AJAX request.
Then in your success function, fire another to stop.
Or if you just want the loading animation:
$(".elmt").addClass("loading");
$.post("verify.php",{
username: u,
password: p
},function(r) {
$(".elmt").removeClass("loading");
// etc...
});
There is a global way to do this using ajaxStart() and ajaxStop(). See How to show loading spinner in jQuery?
If you need to do for all your requests. You could try:
$(document).ajaxStart(function(){
$(".elmt").addClass("loading");
});
$(document).ajaxStop(function(){
$(".elmt").removeClass("loading");
});
But it's not so cool to always display the loading when the request takes little time as it will cause the screen flicking. Try:
var timer;
$(document).ajaxStart(function(){
timer = setTimeout(function(){
$(".elmt").addClass("loading");
},1500);
});
$(document).ajaxStop(function(){
clearTimeout(timer);
$(".elmt").removeClass("loading");
});
By adding a timer, only requests that take longer than 1.5 seconds should be considered long and display a loading icon.
As you see on code below you can do your work on different results of post method
// Assign handlers immediately after making the request,
// and remember the jqxhr object for this request
var jqxhr = $.post("example.php", function() {
alert("success");
})
.done(function() { alert("second success"); })
.fail(function() { alert("error"); })
.always(function() { alert("finished"); });
// perform other work here ...
// Set another completion function for the request above
jqxhr.always(function(){ alert("second finished"); });

weird problem - change event fires only under debug in IE

I have form autocomplete code that executes when value changes in one textbox. It looks like this:
$('#myTextBoxId)').change(function () {
var caller = $(this);
var ajaxurl = '#Url.Action("Autocomplete", "Ajax")';
var postData = { myvalue: $(caller).val() }
executeAfterCurrentAjax(function () {
//alert("executing after ajax");
if ($(caller).valid()) {
//alert("field is valid");
$.ajax({ type: 'POST',
url: ajaxurl,
data: postData,
success: function (data) {
//some code that handles ajax call result to update form
}
});
}
});
});
As this form field (myTextBoxId) has remote validator, I have made this function:
function executeAfterCurrentAjax(callback) {
if (ajaxCounter > 0) {
setTimeout(function () { executeAfterCurrentAjax(callback); }, 100);
}
else {
callback();
}
}
This function enables me to execute this autocomplete call after remote validation has ended, resulting in autocomplete only when textbox has valid value. ajaxCounter variable is global, and its value is set in global ajax events:
$(document).ajaxStart(function () {
ajaxCounter++;
});
$(document).ajaxComplete(function () {
ajaxCounter--;
if (ajaxCounter <= 0) {
ajaxCounter = 0;
}
});
My problem is in IE (9), and it occurs only when I normally use my form. Problem is that function body inside executeAfterCurrentAjax(function () {...}); sometimes does not execute for some reason. If I uncomment any of two alerts, everything works every time, but if not, ajax call is most of the time not made (I checked this by debugging on server). If I open developer tools and try to capture network or debug javascript everything works as it should.
It seems that problem occurs when field loses focus in the same moment when remote validation request is complete. What I think it happens then is callback function in executeAfterCurrentAjaxCall is executed immediately, and in that moment jquery validation response is not finished yet, so $(caller).valid() returns false. I still do not know how alert("field is valid") helps in that scenario, and that could be sign that I'm wrong and something else is happening. However, changing executeAfterCurrentAjaxCall so it looks like this seems to solve my problem:
function executeAfterCurrentAjax(callback) {
if (ajaxCounter > 0) {
setTimeout(function () { executeAfterCurrentAjax(callback); }, 100);
}
else {
setTimeout(callback, 10);
}
}

Categories

Resources