xhr ajax restart after abort - javascript

I have a http long polling polling done like this:
xhr = $.ajax({
type: "GET",
url: "http://localhost/pubsub.php",
...
Ajax returns a xhr object. And I use it in another function to abort the long polling request by doing xhr.abort();
After I do this, how can I restart the long polling request? Is there a method to restart?
Thanks

Here is what I am doing in my projects,
If I see a long delay in the ajax response, I simply abort the previous ajax request and make a new request in the same method as shown below,
Note: I don't call the GetData() mmethod in any loop, rather it is a button click action (say refresh) from application user.
function GetData()
{
if (getDataAjaxCall && getDataAjaxCall.readyState != 4)
getDataAjaxCall.abort();
var searchRequest = {};
searchRequest.Criteria = []; //set some criteria
getDataAjaxCall = $.ajax({
url: 'api/DataController/GetData',
type: 'POST',
dataType: 'json',
data: searchRequest,
success: function (data, textStatus, xhr) {
//do tasks you want on success
},
error: function (xhr, textStatus, errorThrown) {
$.unblockUI();
if (textStatus != 'abort') {
//display error message on actual error
}
}
});
}
I hope the above lines of code might give you some idea.
Also, in the error callback, place a check to catch the abort and handle it separately.

There is no API present to restart the AJAX, But you can simulate the restart of AJAX by calling the AJAX again in error callback function.
var xhr;
function callAJAX() {
xhr = $.ajax({
url: "http://stackoverflow.com/dummyURL",
error: function (xhr, e) {
console.log("Error Occured " + e);
callAJAX(); // Restart the AJAX call
}
})
}
callAJAX();
xhr.abort()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Related

Send AJAX request on each loop iteration after each AJAX success respond

I have an array of ids, and I need to send each id with separate AJAX request. But each next id in the array needs to be sent only after AJAX received a success response from the server for the previuse request.
var idsArrays = [2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020 ];
$.each(idsArrays, function( index, value ) {
var data = "id="+value;
$.ajax({
type: 'POST',
url: formRequiredAction,
data: data,
dataType: 'json',
success: function(resp){
console.log('success ' + resp);
},
error: function(resp){
console.log('error ' + resp);
},
});
});
How can I set pause or wait time for next iteration until ajax will receive success response from the server?
Just make your ajax sychronous and check with a variable if the call has succeeded. EDIT: Forgot it was an .each so break wont work. Just use return.
$.each(idsArrays, function( index, value ) {
var data = "id="+value;
var success = true;
$.ajax({
type: 'POST',
url: formRequiredAction,
data: data,
dataType: 'json',
success: function(resp){
console.log('success ' + resp);
},
error: function(resp){
console.log('error ' + resp);
success = false;
},
async: false
});
if(!success){
return false;
}
});
To chain all the ajax request without locking the browser with synchronous requests you can use promises.
In the example below I use Array.reduce() to digest the list one by one and get the reference of the previous promise. $.when() is used to create the first resolved promise to kick things off. asyncAction() is used to mirror an async operation.
var idsArrays = [2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020 ];
idsArrays.reduce(function(lastPromise, id, index){
var deferred = $.Deferred();
lastPromise.then(function(){
asyncAction(id, deferred.resolve.bind(deferred))
});
return deferred.promise();
}, $.when()).then(function(){
console.log('All Done!');
});
function asyncAction(id, done){
setTimeout(function(){
console.log('Sent', id);
done();
}, 250);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
You can replace asyncAction() with your ajax call, just make sure to resolve the promise calling deferred.resolve() within your ajax success callback. Do note that any failing ajax request will break the chain.

Repeat/loop ajax call on a timer - even if timed out

We have a display board that needs to update every second. The AJAX call to the server triggers a stored proc that is a pretty simple SELECT statement and it takes only milliseconds to execute.
Originally, from time to time because of network latency (or sunspots, or who knows what) this AJAX process would (occasionally, rarely) time out. By tweaking how we handle the timer and by setting the timeout to 0, we have it so it's now running stable and the timeout never happens... yet.
That being said, I'm still nervous that a timeout could still happen. And IF happens, the goal is that it would just keep going. Basically, ignore the timeout and just try again... forever. Nothing like MaxError, or RetryLimit, or TryCount, etc.
Here's what I have now:
setTimeout(function run() {
// When the timer elapses, get the data from the server
GetData();
setTimeout(run, _refreshRate);
}, 1000);
function GetData() {
//console.log("Attempting to obtain the data...");
jQuery.ajax({
url: "something.ashx",
type: "GET",
contentType: 'application/json; charset=utf-8',
success: function(resultData) {
//console.log("Got the data.");
ParseJson(resultData);
// show the last refresh date and time
$('#refreshTime').html(GetDateTime());
},
error : function(xhr, textStatus, errorThrown) {
if (textStatus == 'timeout') {
//console.log("Timeout occured while getting data from the server. Trying again.");
// If a timeout happens, DON'T STOP. Just keep going forever.
$.ajax(this);
return;
}
},
timeout: 0,
});
}
Everything inside of ParseJson(resultData); works great. No issues there. And The timer is setup (I believe) so that it will wait until one GetData() is done before it tries to start another.
I believe that by setting the timeout to 0 that it means "don't ever time out."
My question is this:
Am I correctly handling the error for a timeout? I am using the selected answer in this thread as my guide:
What's the best way to retry an AJAX request on failure using jQuery?
But I don't need a retryLimit limit.
I've also looked at these threads:
How to make the Ajax call again in case Time out error occurs
ajax timeout callback function
I think I've boiled all the info down to a simple solution, but I would like some peer review. Is there a better way to do this?
I'd prefer a solution that only queued a new call when the current had completed. something like..
function poll() {
setTimeout(function () {
GetData();
}, 1000);
}
function GetData() {
jQuery.ajax({
url: "something.ashx",
type: "GET",
contentType: 'application/json; charset=utf-8',
success: function(resultData) {
//...
},
error : function(xhr, textStatus, errorThrown) {
//...
},
complete: function() {
poll();
},
timeout: 0,
});
}
poll();
This way your calls will not risk overlapping anyway.
function GetData() {
//console.log("Attempting to obtain the data...");
jQuery.ajax({
url: "something.ashx",
type: "GET",
contentType: 'application/json; charset=utf-8',
success: function(resultData) {
//console.log("Got the data.");
ParseJson(resultData);
// show the last refresh date and time
$('#refreshTime').html(GetDateTime());
},
error : function(xhr, textStatus, errorThrown) {
if (textStatus == 'timeout') {
//console.log("Timeout occured while getting data from the server. Trying again.");
// If a timeout happens, DON'T STOP. Just keep going forever.
$.ajax(this);
return;
}
},
timeout: 0,
});
}
var myInterval = setInterval(getData, 1000)
// if you want to stop it elsewhere:
// clearInterval(myInterval)
Instead of timeout you could use setInterval

Implementing Callbacks / Deferred Objects with AJAX

Below is a function that is called when a user clicks the "Save" button on a form. When the PreSaveAction function returns true, the form will be submitted. If false is returned, nothing will happen. I'm using an AJAX call to here to validate form values and would like to have PreSaveAction return true if validateUniqueStaff succeeds, and vise versa if it fails.
function PreSaveAction() {
$.ajax({
url: listUrl,
type: "GET",
dataType: "json",
success: validateUniqueStaff,
error: function (data) {
alert("Error: Problem with the AJAX request");
}
});
//if (validateUniqueStaff succeeds) return true, else return false
}
My trouble is that I can't figure out how to incorporate a deferred object here. I've tried running the ajax call synchronously instead, which works in Chrome, but not in IE8 (a requirement).
I'm absolutely stumped. Any advice would be hugely appreciated! Let me know if I can provide any other information.
It is actually possible!
You need to use the developer tools (F12) to get the current java script code behind the button.
Here's how to proceed next:
//1. unbind the current handler:
var saveButton = ...; //your id (looks like ctl00_***)
var saveButtonCallBack = ...; //call back id (looks like ctl00$...)
//2. When document is ready
jQuery(saveButton).unbind('click').click(function(){
PreSaveActionPeter(
function (){
WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(saveButtonCallBack, "", true, "", "", false, true))
}
)
});
//3. Define your function:
function PreSaveActionPeter(callBack)
{
jQuery.ajax({
url: *your url*,
method: "GET",
headers: {
"accept": "application/json;odata=verbose",
},
dataType: "json",
success: function (data) {
if (data.d.results.length > 0) {
callBack();
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(XMLHttpRequest.responseText);
}
});
return true;
}
//4. Override of the default PreSaveAction
function PreSaveAction()
{
return false;
}
Your PreSaveAction() is asynchronous. You can't return a success or failure value from that function. It will return long BEFORE the ajax call has completed.
For asynchronous calls (such as Ajax calls), you HAVE to process the result in a callback that gets called sometime later. You can't pretend to use synchronous coding techniques with an asynchronous operation. It just won't work. PreSaveAction() returns long before the ajax call is done so it's return value will not know the end result of the Ajax call.
If your SharePoint environment requires PreSaveAction() to return true/false and you need to do an Ajax operation in order to figure out if you should return true or false, then you're in a bind. You could make the Ajax call be synchronous, but that's generally a horrible user experience because it locks up the browser during the Ajax call and if you're going cross domain, you can't do synchronous anyway.
The best solution would be to understand what your options are with the PreSaveAction() function and see if you can pass a callback into it that will be called with the final result when the asynchronous Ajax call is done.
That would work something like this:
function PreSaveAction(callback) {
$.ajax({
url: listUrl,
type: "GET",
dataType: "json",
success: function(data) {
var retVal = validateUniqueStaff(data);
// call the callback to report the results of validation
callback(retVal);
},
error: function (data) {
alert("Error: Problem with the AJAX request");
callback(false);
}
});
}
The little bit of searching I did on PreSaveAction() in SharePoint indicates that it has to be synchronous. It was designed for client-side validation only (without Ajax calls to the server). To use it, you will have to return true or false directly from it and thus you can't use asynchronous Ajax calls in your PreSaveAction() implementation because the result won't be known in time. You might be able to make your Ajax call synchronous (which I hate because it can be a bad user experience) or you need to find a different way to do your server-assisted validation.
For form validation, it has been standard practise since time immemorial to issue form.submit() from a submit handler on successful validation, and to return false unconditionally.
Presumably, in the SharePoint environment, you can do the same but with the added minor convolution, in this case, that validation be undertaken only after successful receipt of an AJAX response.
Exactly what you write depends on what your validateUniqueStaff returns.
Assuming validateUniqueStaff to return a boolean (valid/invalid), you would write:
function PreSaveAction() {
var form = this;
//disable Save button here
$.ajax({
url: listUrl,
type: "GET",
dataType: "json"
}).then(validateUniqueStaff, function(jqXHR, textStatus, errorThrown) {
return new Error(textStatus);
}).then(function(valid) {
if(valid) {
form.submit();
} else {
return $.Deferred.reject(new Error('Validation failure')).promise();
}
}).fail(function(e) {
alert(e.message);//this will be either the AJAX error message or the validation failure message
}).always(function() {
//re-enable Save button here
});
return false;
}
Or (more elegantly from PreSaveAction's point of view), assuming validateUniqueStaff to return a Promise that is resolved on success or rejected on failure, you would write :
function PreSaveAction() {
var form = this;
//disable Save button here
$.ajax({
url: listUrl,
type: "GET",
dataType: "json"
}).then(validateUniqueStaff, function(jqXHR, textStatus, errorThrown) {
return new Error(textStatus);
}).then(form.submit, function(e) {
alert(e.message);//this will be either the AJAX error message or the validation failure message
}).always(function() {
//re-enable Save button here
});
return false;
}
I really don't think you should be considering synchronous AJAX, which is as unreliable as it is unnecessary.

Stop ajax function on failure

I'm running a long polling ajax that returns status of request. If failed, I need the ajax to stop. The ajax is written like this:
function someFunction(url){
$.ajax({
url: url,
success: function(data){
if(data.status == 'FAILED'){
//Need this ajax to stop
}
}
});
}
$('some-button').on('click',function(
var url = 'server-url';
someFunction(url);
));
I have to use the someFunction() function as this long polling method is being used by multiple other parts of the code. What should I be doing to stop this function?
try something like this
function someFunction(url){
$.ajax({
url: url,
success: function(data){
if(data.status != 'FAILED'){
//Need this ajax to stop
}
}
});
}
your ajax request is already completed in success. but if status is failed and you want to stop further execution of code than you can use not !
$.ajax returns a wrapped xhr object. Simply use:
var req = $.ajax...
..
req.abort()
var ajaxReq = null;
ajaxReq = $.ajax({
url: url,
success: function(data){
if(data.status == 'FAILED'){
//Need this ajax to stop
}
}
error: function (x, y, z) {
ajaxReq.abort();
}
});
And you can use ajaxReq.abort() to stop ajax call.

How to Stop execution of the JS Code after $.ajax call i.e. when server is processing the AJAX Request

I have a strange issue in JQuery AJAX..
My Steps sequence are as follows:
1) I have a JS Function which I am calling on Button Click Event:
function Click()
{
//I am performing some Validations then making an AJAX Request:
$.ajax({
type: "POST",
url: url,
context: window,
data: datatoPost,
contentLength: contentLength,
async: true,
success: function (response) {
callbackFn(response);
},
error: function (msg) {
this.error = msg;
}
});
// The callback function is called on Successfull AJAX Request
// i.e. callbackFn (See below)
// I am then checking the window.IsValid which I have set in below function;
if (window.IsValid == true) {
// Then Perform another AJAX Request
}
else {
// do nothing
}
}
function callbackFn(response)
{
if(response == 'Valid')
{
window.IsValid = true;
}
else
{
window.IsValid = false;
}
}
2) Now, The Problem is while server is processing the First AJAX Request then the code written after that i.e.
if (window.IsValid == true) {
// Then Perform another AJAX Request
}
else {
// do nothing
}
}
is executed
3) I get window.IsValid = false as first AJAX Request's callback function i.e. callbackFn(response) is not called yet and Even after a Valid response of first AJAX request my second ajax request is not getting executed as window.IsValid variable is not still got set in callback function as callback is not called yet due to server is processing the request.
Please help me I am stuck..
you should then use
async: false,
in you ajax function call. Which is not recomended. The better thing will be to use
if (window.IsValid == true) {
// Then Perform another AJAX Request
}
else {
// do nothing
}
}
within your callback function.
Because your post is asynchronous, the script continues to execute whilst the ajax request is being processed.
Instead, you need to move your tests for window.IsValid into the success function:
function Click()
{
//I am performing some Validations then making an AJAX Request:
$.ajax({
type: "POST",
url: url,
context: window,
data: datatoPost,
contentLength: contentLength,
async: true,
success: function (response) {
callbackFn(response);
if (window.IsValid == true) {
// Then Perform another AJAX Request
// best done as another function.
}
else {
// do nothing
}
},
error: function (msg) {
this.error = msg;
}
});
}

Categories