How to avoid discontinuity in periodical HTTP request by jQuery? - ajax

I am new to jQuery and want to use it to retrieve data from a server every 3 seconds. The web server sends data every 3 seconds in JSON format. The JSON data contains a numerical array field { "samples" : [10,15,-7,19,34,...] }. I wrote the following jQuery ajax request to retrieve data from the server every 3 seconds:
function getData() {
$.ajax({
url : 'http://example.com',
type: 'GET',
success : function(data) {
myData = data.samples;
setTimeout(getData, 3000);
},
dataType : 'json'
});
return myData;
}
However, due to timing jitter, the data sent from the server may not get updated precisely at every 3 seconds. So how should I write the jQuery ajax request to avoid the possible data discontinuity? That is, I want the returned myData contains all fresh new data array elements from each getData() call and does not contain duplicated or missing data samples due to possible timing jitter.

Send the last timestamp that the data was updated on the server along with the other JSON array. Then, when it is time to request data again using your jQuery call, check the timestamp against what you already have. This will give you a way to know if it is the same data, or if it has been refreshed.

I think you may need pass around more info. Include another field in your AJAX called "lastUpdate" with a timestamp. Your javascript can save the last timestamp it got and provide it to the server. The server responds only with samples after that timestamp (so you don't miss any) and won't respond with anything if its still up to date (so you don't duplicate).

There's little point returning myData. (a) the variable is not declared within the function, and (b) the data arrives asynchronously from the server.
As it stands, getData() is guaranteed (at best) to return the data obtained at the previous iteration.
To work with the freshly obtained data, you need to do whatever is necessary with myData within the success function or in a done() callback, as follows :
function getData() {
$.ajax({
url: 'http://example.com',
type: 'GET',
dataType : 'json'
}).done(function(data) {
var myData = data.samples;
//Do whatever is necessary with myData here.
//Call extenal function as necessary to do the job.
setTimeout(getData, 3000);
});
}

Write your code in such a way that takes advantage of the asynchronous nature of ajax. For example,
var interval;
function handleData(data) {
// I handle the data returned from the ajax request.
console.log(data);
}
function getData() {
// I send the ajax request.
$.ajax({
url: 'http://example.com',
success: handleData,
error: function(){
// on error, stop making requests to help with debugging.
console.log(arguments);
clearInterval(interval);
}
});
}
interval = setInterval(getData,3000);
This will result that in most cases, the responses will come in order. You can make that true in all cases if you get rid of the interval and instead call get data 3 seconds after the previous success.
function getData() {
// I send the ajax request.
$.ajax({
url: 'http://example.com',
success: handleData,
error: function(){
// on error, stop making requests to help with debugging.
console.log(arguments);
}
});
}
function handleData(data) {
// I handle the data returned from the ajax request.
console.log(data);
setTimeout(getData,3000);
}
getData();
Side note: the "timing jitter" isn't a jitter at all, it's simply a logic error. The data is always one set behind due to Ajax being Asynchronous.

Related

is it safe to use ajax call every 5 second to check for new inserted database row

im working on a project using asp.net mvc. and im trying to read data from sql server every 5 second and update the user with some feedback.
what I've done till now is using ajax call combined with set timeout.
so every 5 second use ajax call to check if there any new data as shown below.
( the URL is just an example)
function ajaxRequest() {
$.ajax({
url: "https://jsonplaceholder.typicode.com/photos",
success: function (result) {
console.log(result);
},
complete: function (data) {},
}).then(function () {
setTimeout(ajaxRequest, 5000);
});
}
my question is, is there any down side for using set timeout or set interval with ajax like this?
or if there is any better solution for my problem.
worth to mention that the project will be used by at max 4 users at the same time. so I don't think over-loading the server with request will be a problem.

Not able to post JSON Data to MVC Action Method using $.AJAX but I get a Post 200 OK Response

I am trying to post some stringified data to an action method in my MVC controller. Below is the piece of JS Code
function SaveStateForGrid(pGridId, pIsAysnc) {
var grid = $('#' + pGridId).data("kendoGrid");
var tGridState = kendo.stringify(grid.getOptions());
$.ajax({
url: '/Home/SaveGridState',
type: 'POST',
dataType: 'json',
async: pIsAysnc,
data: { pGridState: tGridState, pGridName: pGridId },
success: function (data) {
console.log("Data Saved Successfully");
},
error: function (jqXHR, textStatus) {
console.log("Error while saving grid data " + pGridId);
}
});
}
I am trying to save gridstate info into the db and each grid in my app has different grid state info.
This works sometimes - as in, the post hits the controller method "SaveGridState" if I keep a breakpoint there and so on. On other occasions the breakpoint is not hit and the data is not saved in DB but the code does flow to "success" AJAX callback - no errors and I get a 200POST OK response in the network tab of chrome debugger.
I looked up the data being sent and figured out that on the occasions it fails, there is something about the data being posted which is causing it. Specifically the first param - "tGridState" - a stringified KendoGrid config data. If I replace this data from other successful calls, there is no issue. I have compared the data on different viewing tools and am not able to understand what in the data is breaking this.
Attaching a link to the zip file which contains both "Valid" and "Invalid" data. Any help pls ?
https://www.dropbox.com/s/whfglyk607bnd04/Downloads.zip?dl=0
Few months on from posting this - the module in question was on freeze.
I discovered that the stringified gridstate information (grid config data) included JS functions for grid related events which was causing issues in the stringified data. In fact stringification strips such functions from an object.
Somehow this was preventing me from hitting the breakpoint on the server side even if the data was posted "apparently".
So I wrote a JS function to strip all unnecessary data from my gridstate config data before stringification - and then the post works perfectly.
Voila !

AJAX response undefined.

I am currently creating an AJAX call which queries a controller and returns the appropriate reponse. The only issue is is that the response is coming back as undefined doe to the async nature of the AJAX cal. I am unsure as to how I tell the function to wait for the response. Here is my code:
View:
jQuery(document).on("click", "#payment .membership", function(e) {
e.preventDefault();
var price = SignUpObject.membershipClick(jQuery(this).attr("data-membership-id"));
alert(price);
});
Javascript Library Function (which is within an object):
var SignUpObject = {
membershipClick : function(membershipDetailsId) {
jQuery.ajax({
type : 'POST',
dataType : 'json',
url : 'api/membership-choice',
data : 'membershipid=' + membershipDetailsId
}).done(function(response) {
return response
});
}
}
The PHP that the AJAX call is calling returns the correct response back so I don't need to include them here. Can anyone tell me how to make the AJAX call wait for a response?
Thanks
You've got two problems:
1) You're attempting to call the response synchronously, before the (asynchronous) request has completed.
2) membershipClick does not return the request object, so you've got no means of hooking a completion callback onto it.
To fix:
1) Change the line
jQuery.ajax({...
to
return jQuery.ajax({
2) Change the line
alert(price);
to
price.done(function(response) { alert(response); });
However, the variable price would be better named something like price_request, since it stores a reference to the request, not the actual price (which is the response.)
Change
}).done(function(response) {
return response
});
For:
}), success: function(response) {
return response
};

Page freezes for seconds when ajax post working

When i use jquery's $.post ajax function, page freezes for 2-3 seconds and then data received. Freezing time can change depends on the data received.
How can i prevent this ?
EDIT:
COde i am using, it actually receives very large data
$.post("../ajax_updates.php", { time: last_update }, function(data) {
if (data) {
if (data != "") {
$("#news_feed").prepend($(data).fadeIn('slow'));
}
}
});
If you load big amount of data through JavaScript this is normal, the problem is caused because your request is synchronous which will make your browser to wait this request to end before do anything else.
You need to make your request asynchronous
P.S. Use $.get instead of $.post to get information from the server, in some cases - specially if you code work under Windows IIS you will get an error about that.
P.S-1. And it make sense $.get is for getting data from the server and $.post is for sending data.
Try this:
$.ajaxSetup({
async: true
});
$.get("../ajax_updates.php", { time: last_update }, function(data) {
if (data && data != "") {
$("#news_feed").prepend($(data).fadeIn('slow'));
}
});
When you send the ajax request make sure that async is set to true. If it is set to false, the browser will freeze untill a response is received.
http://api.jquery.com/jQuery.ajax/

How can I manipulate an Ajax response before it's injected into the DOM?

Here is what I have so far:
$(function () {
dataValModify('body');
$('body').bind('ajaxSuccess', function (e, xhr, settings) {
dataValModify(xhr.responseText);
});
});
function dataValModify(elem) {
// Code to modify elements within the response.
}
How can I take the Ajax response and modify it before it is injected into the DOM? Previously, I was binding ajaxComplete and modifying the DOM directly after injection, but I would like to modify the response instead. I don't think it makes a lot of sense to find elements in the Ajax response and use them to modify the DOM. I send the xhr.responseText into my function so that I don't reapply the modifications to the rest of the body, which will have already been modified by the time of an Ajax call. Also, is there something better than xhr.responseText to use for this? I couldn't get xhr.responseHTML to work.
EDIT: Right now I'm just using a simple test Ajax call to return an MVC partial view:
$('#ajaxTest').load('<MVC Route>')
If I'm understanding your requirements correctly, they are as follows:
Make an asynchronous HTTP request to get some HTML
Modify the returned HTML using the dataValModify() function
Insert the modified HTML into your element with the ID: 'ajaxTest'
If so then it sounds to me like you need to make a lower level ajax call than what you're using at present i.e. $(elem).load()
Essentially the call to .load() is a wrapper for $.get() followed by a call to $(elem).html(someContent) where "someContent" is the responseText from the HTTP request.
Therefore if you want to modify the response before it's injected into the DOM, then you can do something similar to the following:
$.ajax({
type: "GET",
url: "<MVC Route>",
dataType: "html",
success: function(jqXHR, textStatus, errorThrown){
// Your HTTP call was successful but nothing else has happened with the response yet
// Therefore you can now do whatever you want with the it...
// First modify the HTML using the dataValModify function
// Assumption being that your function returns the modified HTML string
var myModifiedHTML = dataValModify(jqXHR.responseText);
// Inject the modified HTML
$('#ajaxTest').html(myModifiedHTML);
}
});
You can use ajaxComplete to modify the responseHTML itself.
$('body').ajaxComplete(function(e, xhr, settings) {
dataValModify(xhr.responseHTML);
});
Update: I haven't tried it, but it might help:
$.ajaxSetup({
converters: {
"text html": function( textValue ) {
if ( valid( textValue ) ) {
// Some parsing logic here
return dataValModify(textValue );
} else {
// This will notify a parsererror for current request
throw exceptionObject;
}
}
}
});
More info here: http://api.jquery.com/extending-ajax/

Resources