Reputation: 18761
I'm generating PDFs in the background through an AJAX call. Generating the PDF takes some time (about a second or so).
The below works fine, but the problem is that I run out of memory. Hence I'd like to only start the computation (i.e. only issue the AJAX call) when the previous AJAX call is done.
I've played around with async: false
but that freezes my page, which is unwanted behavior (and the use of async
is deprecated anyhow).
My code:
$("div[data-myid]").each(function(){
var myid= $(this).data('myid');
var my_div = $(this);
$.ajax({
url: "/my_ajax/" + myid + "/",
}).done(function (data) {
my_div.html(data.message + ' <a href="' + data.url + '">Download</a>');
});
});
HTML:
<table>
<tr>
<td><div id="div_260" data-myid="260">Queued..</div></td>
</tr>
<tr>
<td><div id="div_259" data-myid="259">Queued..</div></td>
</tr>
</table>
Note the table is dynamically generated and generally contains 100+ rows.
Any idea on how to best approach this?
Upvotes: 2
Views: 2044
Reputation: 5244
Next ajax should be fire only after current ajax call get finished. Below code will help you to achieve it.
Steps to achieve it.
doAjax
function will be called in ajax success function. Therefore,
Next ajax will be fired only after current get finished.This is my code:
<script type="text/javascript">
var elementArray = [];
//Code to push all divs in elementArray
$(document).ready(function(){
$("div[data-myid]").each(function () {
elementArray.push($(this));
});
// First ajax call.
doAjax(0);
});
//Function to ajax fire
function doAjax(arrCount)
{
var myid = elementArray[arrCount].data("myid");
var my_div = elementArray[arrCount];
$.ajax({
url: "/my_ajax/" + myid + "/",
type:"POST",
dataType:"json",
success: function (data) {
if (arrCount < elementArray.length-1) {
{
my_div.html(data.message + ' <a href="' + data.url + '">Download</a>');
arrCount++;
//Next ajax call when current ajax call has been finished.
doAjax(arrCount);
}
}
});
}
</script>
Upvotes: 6
Reputation: 2333
Maybe like this :
function postponeAjax(index,element){
var myid= $(element).data('myid');
var my_div = $(element);
setTimeout(function(){
$.ajax({
url: "/my_ajax/" + myid + "/",
}).done(function (data) {
my_div.html(data.message + ' <a href="' + data.url + '">Download</a>');
});
},index*2000);
}
$("div[data-myid]").each(function(index,element){ // if I remember well
postponeAjax(index,element)
});
This is kind of hacky solution but I think it should work :) Here is a replit with basic example using for loop https://repl.it/CfJA. The 2000 delay, you modify it to fit creation time of pdf with some tolerance of + 1 second :)
EDIT :
There is this handy function that is called when last ajax call is completed
$(document).ajaxStop(function() {
// place code to be executed on completion of last outstanding ajax call here
});
So we can do something like this:
var number_of_elements = $("div[data-myid]").length;
var current_index = 0;
var myid, mydiv;
function doAjax(){
mydiv = $("div[data-myid]:eq("+current_index+")"))
myid = mydiv.data('myid');
$.ajax({
url: "/my_ajax/" + myid + "/",
}).done(function (data) {
my_div.html(data.message + ' <a href="' + data.url + '">Download</a>');
});
current_index++;
}
//repeat until there is no more elements
$(document).ajaxStop(function(){
if(current_index < number_of_elements){
doAjax();
}
});
//init the sequence
doAjax();
I have not tested this, so notify me if it does not work :D
Upvotes: 1