I need to return a large amount of json data via an ajax call. Is there a built in jquery or javascript function to handle "chunking" of the data
ie: I need to be able to handle the data as it is returned by keeping the ajax call open and receiving chunks of data as it is sent from the server.
One method might be a self referencing ajax polling function something like...
(function getData() { setTimeout(function() {
$.ajax({
url: "locationofserver",
success: function(data){
// handle data returned (append chunks?)
// get next bit
getData();
},
dataType: "json"});
}, 20000);
})();
Where the first call returns information about the data length and how many chunks are available. This of course means the server needs to manage the breaking up of the data into chunks...
I would ask why you would need to chunk it though instead of just ensuring a persistent ajax connection until done? If you are truly looking to handle a data stream then maybe http://signalr.net/ or other push technology?
Related
After reading this thread jQuery Ajax Request inside Ajax Request
Hi everyone I need to have explanations about such a situation.
I've just been working on the code of a former member of my development team and found many parts of the code where he makes asynchronous ajax calls within other ajax calls.
My question is: can anyone explain the advantages and disadvantages of this practice and whether it is a good or bad practice?
Here is an example of code:
// first ajax (starting ajax call)
$.ajax({
url: "script1.php",
type: "POST",
data: {paramFisrtAjax: "first-ajax"},
success: function(response) {
alert(response);
}
});
script1.php
<script>
// second ajax
$.ajax({
url: "script2.php",
type: "POST",
data: {paramFirstAjax: "<?= $_POST['paramFisrtAjax'] ?>", paramSecondAjax: "second-ajax"},
success: function(response) {
alert(response);
}
});
</script>
<?php
// some operations on database server
echo "page2 operations with param: paramFirstAjax-> {$_POST['paramFirstAjax']}";
?>
script2.php
<?php
// some operations on database server
echo "page3 operations with params: firstParam -> {$_POST['paramFisrtAjax']} and secondParam-> {$_POST['paramSecondAjax']}";
?>
Something tells me it's not a good thing becouse i think the correct way is use the callback function success.
Like this: jquery nested ajax calls formatting
There is an advantage and a disadvantage here.
The Advantages are:
1) You make an async call, making the request a lot faster. You do not wait for the callback function, thus do not wait for your response which might take time to return. You do everything on the background rather then 'straight forward'.
This is understandable when you call multiple methods and you do not want the delay in waiting for the callback.
2) You are able to fetch a far greater amount data through your call while minimizing the need of the end client to wait.
This is useful when you have a big amount of data to display and you want to make it with minimal effort.
The Disadvantages:
1) Error handling is a pain. If something fails within the inner calls, it takes time to detect were the failure occurred and on which method.
When waiting for the callback, you can detect right away where the error occurred, as it will return a response of success or error,
2) if there is a mismatch on the data, it is hard to track back and see where the missing part took place, you will have to go through each request one by one to detect and use developer tools and/or fiddler as well, since those are async calls at the end.
3) it is easy to put too much effort on the client, since maintaining this kind of technique might result in calling multiple methods that will work together at the same time, thus creating overload on the client, locks on the threads or DB when working with server side code and more.
This explained, you can now decide for yourself with which type of method you would like to continue further in your code.
If there is jquery ajax loading and I fire another ajax by quickly clicking the button, it kind of gets stuck. How can I handle multiple requests fired together?
How do I do following?
Discard/abort all previous requests and only process the latest one.
Do not allow new request until previous request completes (variation: can be same ajax request or any new ajax request from the page).
AJAX is Asynchronous. So you can fire them at the same time.
Or in the success callback (or .done() callback), you can call one request after another. So it will be easy to manage your issue (you click the button but get stucked), because you can control.
$.ajax({
url: "http://..."
})
.done(function( data ) {
// Other AJAX call
// or restore disabled elements
// while you were receiving the response.
});
If you want a work-around, just tell me.
you can use ajax "beforeSend" to lock the current request.So that user can send a new request only if the previous one is done. As for the process sequence, you can use a global value to store data and always assign it with the new response value.
function request(callback){
if(!$btn.hasClass('disabled')){
$.ajax({
type:'...',
url:'...',
beforeSend:function(){
$btn.addClass('disabled');//so that user cannot send a new request
},
success:function(data){
window.g_data = data;
callback && callback()//success callback
$btn.removeClass('disabled');
}
})
}
}
function callback(){
//process window.g_data
}
Have a look at this library:
Async is a utility module which provides straight-forward, powerful functions for working with asynchronous JavaScript.
Async
Scenario:
So I have a javascript component that basically holds an instance of some global list of data (In my actual application, this resides in a Flux Store, but I'm just referring it as a global variable for simplicity's sake).
It contains functions to ADD/DELETE data by making AJAX calls to a REST API.
Design:
Since I want the users to be able to immediately view the updated list, instead of having to wait until the Ajax success callback, I'm performing an "Optimistic Update."
That is, I'm updating the list before performing the actual AJAX call, while keeping the original copy of the list in localStorage in case the AJAX call fails.
(1) If the AJAX call succeeds, then update the list with the API response (which should basically be the same as the optimistically updated list)
(2) If the AJAX call fails, then undo the optimistic update by retrieving the original copy from the localStorage.
Here is my Implementation:
// Some global data list
var myData = ["data1", "data2", ...];
function addData(dataToAdd) {
// Store original in cache before optimistic update
localStorage.set("MY_DATA", myData);
// Do optimistic update
myData = myData.concat(dataToAdd);
$.ajax({
url: REST_API_ADD,
method: "POST",
data: { data: dataToAdd },
dataType: "json",
success: function(response) {
// API returns the updated list when success
myData = response;
},
error: function(xhr, status, err) {
console.log(err);
// Cancel optimistic update and retrieve old data from cache
myData = localStorage.get("MY_DATA");
}
});
}
function deleteData(dataToDelete) {
// Store original in cache before optimistic update
localStorage.set("MY_DATA", myData);
// Do optimistic update
// I'm using Underscore.js here to delete data from list
myData = _.without(
myData,
_.findWhere(myData, {id: dataToDelete.id})
);
$.ajax({
url: REST_API_DELETE,
method: "DELETE",
data: { data: dataToDelete },
dataType: "json",
success: function(response) {
// API returns the updated list when success
myData = response;
},
error: function(xhr, status, err) {
console.log(err);
// Cancel optimistic update and retrieve old data from cache
myData = localStorage.get("MY_DATA");
}
});
}
Is there anything wrong with this idea?
My primary concern is a race condition that might occur when the user performs ADD and DELETE operations almost simultaneously..
I've thought of possible scenarios, but it seems like concurrency is not a problem in my case, since the callback functions never modify the localStorage. All they do is "get."
Can anyone think of situations where my design might cause problems?
Is this a bad design overall? If so, then can you suggest an alternative approach?
Thanks
My primary concern is a race condition that might occur when the user
performs ADD and DELETE operations almost simultaneously..
There should be no concern here since AJAX executed from the UI thread isn't asynchronous in terms of parallelism. Web browsers use an execution queue where each enqueued action is dequeued synchronously.
For example, it will never happen that you modify the DOM and perform an AJAX request concurrently. Actually, UI tasks have more priority than AJAX, but anyway they will be executed one by one.
AFAIK, there's only one chance that you will run in concurrency problems: Web workers. Unless you use them, you're absolutely safe.
I think this is not a bad design, but you can still have more control over users. At least you can block them from taking another action while an ajax call waiting for success.
I can think of one problem: If you are dealing with lots of data, writing to and reading from the localStorage may lead to performance problems.
Besides these, there should be no problems at all within your approach.
I have links in a JQuery DataTable that use JQuery UI's tooltip feature. Each link has a tooltip that is populated by an Ajax call. I would like to limit the number of Ajax calls to as few as possible. The DataTable uses server-side processing, and the results are paginated, so there will never be more than ten links on the page at any one time.
The data that is returned by the Ajax call will never change and thus can be safely cached. In my testing, I have seen that the browser does cache the result of each Ajax call, so that it only makes one call per link, and then uses the cache thereafter. My concern is that some user might have their browser configured in such a way that it doesn't use the cache for some reason, and they will be firing off one Ajax call after another, every time they mouse over a link.
Here is the JavaScript for the tooltip:
$('.jobId').tooltip({
content: function(callback) {
var jobId = $(this).text();
$.ajax({
url: 'myUrl',
data: {jobId: jobId},
dataType: 'json',
success: function(data) {
var html = formatResults(data);
callback(html);
},
error: function() {
callback('An error has occurred.');
}
});
}
});
I considered storing the result of each Ajax call in a JavaScript object declared at global scope, and then checking that before making the Ajax call, but I have the vague sense that this might cause a memory leak somehow.
var gJobs = new Object();
$('.jobId').tooltip({
content: function(callback) {
var jobId = $(this).text();
if (gJobs[jobId]) {
callback(gJobs[jobId]);
} else {
$.ajax({
url: 'myUrl',
data: {jobId: jobId},
dataType: 'json',
success: function(data) {
var html = formatResults(data);
gJobs[jobId] = html;
callback(html);
},
error: function() {
callback('An error has occurred.');
}
});
}
}
});
I am also concerned that if the table has a large number of rows, the gJobs object could end up using a lot of memory. To prevent the gJobs object from growing indefinitely, every time the user goes to the next or previous page of results in the DataTable, I use the fnDrawCallback function to reinitialize gJobs:
$('#jobsTable').dataTable({
...
"fnDrawCallback": function() {
gJobs = new Object();
}
});
I should mention that since the data returned by each Ajax call doesn't change, I could also just store the data in the JSP as static text, and populate the tooltips that way instead of using Ajax. However, I have to make a separate web service call to get the data for each link, and rather than make ten web service calls every time the user pages forward or back, I would rather load the data on demand via Ajax.
Is there anything wrong with this approach? Is there any way this can cause a memory leak? Should I explicitly delete all the properties of gJobs before reinitializing it? Thanks for your help.
I'm writing some JavaScript/AJAX code.
Is there anyway to ensure that the server receives the XML requests in the order that they are sent?
If not with plain Ajax, do I get this guarantee if I send everything over a single WebSocket?
Thanks!
If it is of utmost importance that they're received in the proper order, and attaching an iterating id to the form isn't enough:
msg_number = 1; sendAJAX(msg_number); msg_number++;
Then I'd suggest building your own queue-system, and send each subsequent file as the callback of the previous one.
Rather than each element having its own AJAX-access, create one centralized spot in your application to handle that.
Your different AJAX-enabled sections don't even need to know that it is a queue:
AJAX.send({ url : "......", method : "post", success : func(){}, syncronous : true });
On the other side of that, you could have something like:
AJAX.send = function (obj) {
if (obj.synchronous) {
addToSyncQueue(obj); checkQueue();
} else { fireRequest(); }
};
Inside of your sync queue, all you'd need to do is wrap a new function around the old callback:
callback = (function (old_cb) {
return function (response) {
checkQueue();
old_cb(response);
};
}(obj.success));
obj.success = callback;
AJAX.call(obj);
Inside of checkQueue, you'd just need to see if it was empty, and if it wasn't, use
nextObj = queue.shift(); (if you're .push()-ing objects onto the queue -- so first-in, first-out, like you wanted).
A couple of options come to mind:
Send them synchronously, by waiting for a successful response from the server after each XML request is received (i.e. make a queue).
If you know the number of requests you'll be sending beforehand, send the request number as a tag with each request, e.g. <requestNum>1</requestNum><numRequests>5</numRequests>. This doesn't guarantee the order that they're received in, but guarantees that they can be put back in order afterwards, and has the added benefit of being sure that you have all the data.
At my company we use this little ajaxQueue plugin, written by one of the core jQuery contributors:
http://gnarf.net/2011/06/21/jquery-ajaxqueue/