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);
Related
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 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/
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/
I have an ajax application, which has code something like this:
$.ajax({
type: "GET",
url: "data.txt",
beforeSend:function(){
},
success:function(response){
just update responsed data;
}
});
this call is made every second and it just updates the latest data from 'data.txt' which is being updated on server using cron job. Now since it's only function is to update latest data each second so I'll be more interested in the latest ajax call ; so how can I terminate old ajax call that has crossed 4 seconds but yet not completed so that I can reduce the server traffic. And any suggestion if using 'data.html' or 'data.php' instead of 'data.txt' would increase the application performance ? And which web server can perform better than Apache for ajax driven application ? I need these help urgently ; Please do help.
You could keep track of when your last successful update time was.
function NowMS() {return parseInt(new Date().getTime())}
dataLastUpdateT = -Infinity;
$.ajax({
type: "GET",
url: "data.txt",
success: function(response){
if (NowMS() > dataLastUpdateT) {
use(response);
dataLastUpdateT = NowMS();
}
}
}
I don't know how you have it setup at the moment but perhaps it would be better to run your next AJAX call after the latest one completed (or returned an error). So it would be something like:
(function updateData() {
$.ajax({
type: 'GET',
url: 'data.txt',
beforeSend: function() {
// Do stuff
},
success: function(response) {
// Handle response
updateData();
}
});
})();
I don't know if there is any performance changes in changing the file type.
Edit: If you do need to just kill the request, you can do so using the technique explained here.
You could try this:
function getData(){
$.ajax({
type: "GET",
url: "data.txt",
timeout:4000,
beforeSend:function(){
},
success:function(response){
},
error:function(){
},
complete:function() {
setTimeout(function(){getData();},1000);
}
});
}
getData();
this way the ajax request timeouts after 4 seconds and retries each second (regardless of success or timeout)
Also have a look at nginx for example, it is fast and uses less memory than apache to handle client connections
I've a web application which calls a webservice with ajax. This webservices returns me the configuraiton for my app, so the ajax call needs to be set at {async:false}.
Everything works fine when my server is up, but in the case it's not, my browser just freezes. Even if I set a timeout in my ajax call setup.
I've a error handler function which is never called even if the timeout is passed.
Someone has ever been confronted to that situation ?
#Edit : My problem can be solved by doing asynchronous call
As the browser is single threaded it would be better to process the config
returned in the callback success, and handle any errors in the error callback.
$.ajax({
url: "mydomain.com/url",
type: "GET",
dataType: "json",
data: $.param( $("Element or Expression") ),
complete: function() {
//called when complete
},
success: function() {
//called when successful
},
error: function() {
//called when there is an error
},
});