Ajax hits success callback before backend call finishes? - javascript

I'm running into the following issue:
an ajax call goes out to a backend jsp call
sometimes(?) the success() callback on the ajax call is hit before the backend call finishes
I didn't think this was possible :)
The code looks something like this:
var opt = {
form: $form,
retry: '0',
retryHandler: function(...) { alert(...);},
dataType: 'xml',
url: url,
error: function(xhr, status, e) { ... }
timers: {},
timeout: timingConfig.timeout,
beforeSend: function(xhr) { ... },
success: function(data, status, xhr) {
// breakpoint in here
}
One breakpoint in success callback, and one breakpoint in the backend jsp.
Both are hit at roughly the same time, where I'd expect success() to not be called until the the backend call finishes.
Any ideas on what's going on here? O_o

Related

Ajax Request sometimes causes `XHR failed loading: POST` error

I am trying to run a simple Ajax Request to pass a JSON object from my Javascript file to my Python file in Django. However half the time, I get the error XHR failed loading: POST when I run it as follows:
var csrf = $("[name=csrfmiddlewaretoken]").val()
$.ajax({
type: "POST",
url: "/fridge",
data: {
"fridgeitems": JSON.stringify(fridge),
"csrfmiddlewaretoken": csrf
},
dataType: "json",
timeout: 5000,
}).done(function(data) {
console.log(data.fridge);
}).fail(function(jqXHR, status) {
alert('Request could not complete' + status);
});
})
// rest of code
In my python file:
fridgeitems = request.POST['fridgeitems']
# do something with the data
response_data = json.dumps(fridgeitems)
return JsonResponse({"fridge": fridgeitems}})
I think what is happening is that when the Ajax request is placed the rest of the code runs, finishes and quits the function before ajax call has time to load. I have tried including timeout in my Ajax call however this appears to do nothing. How can I make the function wait for the Ajax call to finish?
Your problem is most likely that your request is timing out after a while of not getting response from the server. One likely cause is due to a slow network.
To handle this, do either or both of two things:
1. Handle the case where an request doesn't complete with the fail() method of the jqXHR object.
2. Include a timeout in the ajax request settings.
I illustrate using the combined strategy below:
var csrf = $("[name=csrfmiddlewaretoken]").val();
$.ajax({
method: "POST",
url: "/fridge",
data: {
"fridgeitems": JSON.stringify(fridge),
"csrfmiddlewaretoken": csrf,
},
dataType: "json",
timeout: 5000 // 5000ms
}).done(function(data) {
// is called if request is successful
console.log(data.fridge);
}).fail(function(jqXHR, status) {
// is called if request fails or timeout is reached
alert('Request could not complete: ' + status);
});
Notice, the use of the jQuery deferred objects methods: done() and fail() instead of sucess() and error(). The later is deprecated.

How to call code-behind method from 'success' in ajax callback?

How to modify below code to use 'success' to call testMethod() in code-behind ?
I need to wait for return value from testMesthod() and process it.
$.ajax( {
url : 'myPage.aspx/testMethod',
type : "POST",
contentType : "application/json; charset=utf-8",
data : "{'name':'" + aNb + "'}",
dataType : "json"
}).done(function() {
alert("ok");
}).fail(function() {
alert("not ok");
});
Above code does not work because somehow latest JQuery version (1.10.1) gets overwritten by 1.3.2.
Thank you
You would need to pass the callback function to the function that wraps your $(ajax).
function getData(ajaxQuery, callBack){
var ajaxHREF = 'your url';
$.ajax({
url: ajaxHREF,
type: "post",
data: ajaxQuery,
beforeSend: function ( xhr ) {
xhr.overrideMimeType("application/json");
},
success: function(response, textStatus, jqXHR){
var jsonData = $.parseJSON(response);
callBack (jsonData);
},
However, a much better way of doing this is the global success event. It is better because you have all of the properties of the call available to you to enable dynamic processing of the results. Create the global success event inline = $(document).ajaxSuccess this gets called for all jquery ajax success events so you need to differentiate which calls apply to your specific handler (to each global handler).
$(document).ajaxSuccess(function(event, xhr, settings) {
var query = settings.data;
var mimeType = settings.mimeType;
if (query.match(/ameaningfulvalueforthishandler/)){
if(mimeType.match(/application\/json/)){
var jsonData = $.parseJSON(xhr.responseText);
}
}
}
Thank for replies, but I still do not see how callbacl can help me.
I need to call webmethod in code-behind: testMethod()
Ajax call does it, url = "myPage.aspx/testMethod" will 'call' webmethod testMethod(),
but it's asynchronous and returns quickly into 'success' section of ajax call.
But, I need to Wait for testMethod() to finish processing, retrieve result returned by testMethod() and process it.
Asynchronous ajax will return us into 'success' without waiting for testMethod() to finish,
and we will not get any data in response.
So, how callback helps me to achieve it?
function getData(ajaxQuery, callBack){
var ajaxHREF = "myPage.aspx/testMethod";
$.ajax({
url: ajaxHREF,
type: "post",
data: ajaxQuery,
beforeSend: function ( xhr ) {
xhr.overrideMimeType("application/json");
},
success: function(response, textStatus, jqXHR){
var jsonData = $.parseJSON(response);
callBack (jsonData);
});
Thank you
#Karen Slon - If I understand the question correctly, I think you need to conceptually separate the client side from the server side. The callback in .success/.done or global ajaxSuccess event enable your web page to initiate the request and keep on processing while the server side is processing your request 'myPage.aspx/testMethod'. When it completes successfully it returns to the success event. Now if testMethod does not return anything then you will find yourself in the success event event without a result. But you cannot get there unless web method testMethod has completed successfully and returned control. The .done event in your example only has alert("ok");. What makes you believe that the web method testMethod is not complete when the .done event occurs?
Look at these posts for better examples:
jQuery.ajax handling continue responses: "success:" vs ".done"?
http://encosia.com/using-jquery-to-directly-call-aspnet-ajax-page-methods/
http://api.jquery.com/category/deferred-object/

use paging with ajax call in a while loop

In a javascript function I make a call to the server and get batches of 10 records back. I need to do this untill I've had all records.
To start I made a while loop where in the error callback of the ajax call I would end the while loop.
Halfway through I started to realize that that would not work, as the ajax call is async and I would thus fire loads of requests in the loop. I'm sure there is a standard pattern to do this but I don't know how.
How can I do the ajax call in a loop and perform it as long as the call is not returning an error?
Pseudo code I was building:
var stillRecordsAvailable = true;
while (stillRecordsAvailable) {
// get the next batch of records
$.ajax({
url: '/getrecords.json',
data: {data_set_id: dataset.id},
type: 'GET',
success: function(data, textStatus, xhr) {
// do something
},
error: function(xhr, textStatus, errorThrown) {
// nothing left to do
stillRecordsAvailable = false;
}
});
Thanks for pointing me in the right direction
You'd probably want to just wrap the ajax call in a function that is called on the ajax success callback:
function getRecords(data, textStatus, xhr) {
if (data) {}; // do something...
$.ajax({
url: '/getrecords.json',
data: {data_set_id: dataset.id},
type: 'GET',
success: getRecords
});
}
This will only work if your server/API returns an error when no more records exist; however, this may not be the best pattern. A more elegant way of tracking asynchronous event state is through a deferred/promise pattern. jQuery has a great implementation: http://api.jquery.com/category/deferred-object/

Delay between repeated AJAX call to a web method

I have a ASP.Net web app with jquery implemented on the client side. within a while loop, the client side jquery script makes an asynchronous call to a web method in the server side code. The call returns the status of a long running server side task which jquery uses to update the user. The goal is to have jquery repeatedly call the server until the status is complete, once done it breaks out of the while loop and notifies the user thatthe task is complete.
My problem is that the below code runs in a while loop, but I want to make it delay or sleep between each call in order to prevent overwhelming the server with status requests. I tried calling setTimeout in the code below, but it only works with the initial ajax call, every subsequent call occurs back to back. Is there a way to efficiently delay each subsequent call to the server? Is this the most efficient way to achieve the kind of behavior I'm describing? Ideally I'd like a 2-5 second delay between each call.
I have the following code
Client Jquery:
var alertTimerId;
$('input[name=btnStatus]').click(function () {
var result = false;
//Loop while server reports task complete is true
while (!result) {
alertTimerId = setTimeout(function () {
$.ajax({
type: "POST",
url: "Default.aspx/GetStatus",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
async: true,
success: function (msg) {
if(msg.d != false)
result = msg.d;
},
error: function (xhr, ajaxOptions, thrownError) {
alert('AJAX failure');
}
});
}, 2000);
if (count > 0) {
count--;
}
}
});
Server Side ASP
[System.Web.Services.WebMethod]
public static bool GetStatus()
{
return result;
}
How about something like the following? The idea is that the Ajax call is encapsulated in a function, doAjax(), and then from within the Ajax success handler if the result is false you use setTimeout() to queue up another call to doAjax, otherwise you take whatever action you want to take for a true result. (You could optionally call doAjax() from the Ajax error handler too.)
$('input[name=btnStatus]').click(function () {
function doAjax() {
$.ajax({
type: "POST",
url: "Default.aspx/GetStatus",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
async: true,
success: function (msg) {
if (!msg.d)
setTimeout(doAjax, 2000);
else {
// Success! Notify user here
}
},
error: function (xhr, ajaxOptions, thrownError) {
alert('AJAX failure');
}
});
}
doAjax();
});
(Note: I've removed the if statement with count, since it seemed to have no relevance to the question. If your real code uses it just update it within the Ajax success handler too.)
Underscore.Js has a .throttle() helper function:
throttle_.throttle(function, wait)
Creates and returns a new, throttled version of the passed function, that, when invoked
repeatedly, will only actually call the original function at most once
per every wait milliseconds. Useful for rate-limiting events that
occur faster than you can keep up with.
var throttled = _.throttle(updatePosition, 100);
$(window).scroll(throttled);

Terminate ajax call after timeout

I am executing the following ajax call.
I am testing timeout mechanism and thus suspending my server on purpose.
The problem is that although I do receive timeout in the client after one second the call as I see it in firebug still continues.
I guess there should some way to stop the call execution but I did not find one.
$.ajax({
url: url,
dataType: "jsonp",
jsonp: "jsoncallback",
timeout: 1000,
success: (function(w) {
...
},
error: function(XHR, textStatus, errorThrown) {
alert("Error");
}
});
Appreciate the help.
You can try this
...
error: function() {
window.stop()
}
...
Try this Abort Ajax requests using jQuery

Categories

Resources