It's been a while since I have tried working with JavaScript, so please bear with me. I am working on an application that offers reports on student data. The backend is PHP.
The database that we use for these reports has to be refreshed from time to time from a central warehouse. The refresh happens at the discretion of the end user and is not automated for various reasons not worth going into here.
The refresh takes at least 10 minutes. So it would be painful for the browser to sit there loading for that amount of time with no feedback going to the user. I figured the best way to offer feedback to the user would be through a simple JQuery script that keeps the user up-to-date on the progress of the update.
Here is the script:
var n = 0;
function increment() {
n++;
return n;
}
$(document).ready(function() {
$("#popme").click(function(event) {
n = 0;
$.getJSON('/path/to/json_pids', function(data) {
var numRecords = data.length;
$("#pop-result").html('<p>' + numRecords + ' records</p>');
$.each(data, function(row) {
$.ajax({
url: '/path/to/json_student_info/' + this,
success: function() {
increment();
$("#pop-result").html('<p>' + n + ' / ' + numRecords + ' records</p>');
}
});
});
});
});
});
What's happening in this script:
There's a div
with the pop-result
ID that gets updated. The /path/to/json_pids
returns a JSON array of the matching student IDs.
From there, the script loops through each record and calls /path/to/json_student_info/{student_id}
, but does not require anything in return. This second URL calls a script on the backend that creates/updates that student's record in the reporting database.
On success, the script is supposed to increment the number displayed in pop-result
so that the user can see the progress toward pletion of the script.
The result and my question
The result is a bit of a mess. The JS Console is showing a whole long line of ERR_INSUFFICIENT_RESOURCES
errors. The script never makes it all the way through all the records. It might reach ~4,000 out of ~11,000 records and just die from there.
I have a feeling I'm making a rookie mistake here. I've been looking for similar scenarios over the past couple of days but haven't found anything that helps. The best idea I can find is to break the data into chunks, but I still receive the same error and behavior. Is there an alternative/better way to acplish what I am trying to acplish, or a way to make this script less intensive on the browser?
It's been a while since I have tried working with JavaScript, so please bear with me. I am working on an application that offers reports on student data. The backend is PHP.
The database that we use for these reports has to be refreshed from time to time from a central warehouse. The refresh happens at the discretion of the end user and is not automated for various reasons not worth going into here.
The refresh takes at least 10 minutes. So it would be painful for the browser to sit there loading for that amount of time with no feedback going to the user. I figured the best way to offer feedback to the user would be through a simple JQuery script that keeps the user up-to-date on the progress of the update.
Here is the script:
var n = 0;
function increment() {
n++;
return n;
}
$(document).ready(function() {
$("#popme").click(function(event) {
n = 0;
$.getJSON('/path/to/json_pids', function(data) {
var numRecords = data.length;
$("#pop-result").html('<p>' + numRecords + ' records</p>');
$.each(data, function(row) {
$.ajax({
url: '/path/to/json_student_info/' + this,
success: function() {
increment();
$("#pop-result").html('<p>' + n + ' / ' + numRecords + ' records</p>');
}
});
});
});
});
});
What's happening in this script:
There's a div
with the pop-result
ID that gets updated. The /path/to/json_pids
returns a JSON array of the matching student IDs.
From there, the script loops through each record and calls /path/to/json_student_info/{student_id}
, but does not require anything in return. This second URL calls a script on the backend that creates/updates that student's record in the reporting database.
On success, the script is supposed to increment the number displayed in pop-result
so that the user can see the progress toward pletion of the script.
The result and my question
The result is a bit of a mess. The JS Console is showing a whole long line of ERR_INSUFFICIENT_RESOURCES
errors. The script never makes it all the way through all the records. It might reach ~4,000 out of ~11,000 records and just die from there.
I have a feeling I'm making a rookie mistake here. I've been looking for similar scenarios over the past couple of days but haven't found anything that helps. The best idea I can find is to break the data into chunks, but I still receive the same error and behavior. Is there an alternative/better way to acplish what I am trying to acplish, or a way to make this script less intensive on the browser?
Share Improve this question asked May 2, 2016 at 15:38 JoeventuresJoeventures 861 gold badge1 silver badge4 bronze badges 4- 1 you're sending 11k ajax requests as fast as the browser will allow to the server. that's quite a bit of processing. Maybe throttle it back a bit. – Kevin B Commented May 2, 2016 at 15:43
-
1
Sounds like you're inadvertingly causing a DOS style drag on your server which is not surprising if you take into account that the async nature of the
$.ajax
call will allow the browser to launch a large amount of requests in a super short time period. I'm thinking that you're consuming all available resources, filling the request pool or app pool, and then dying. You could try launching each subsequent request after the first in the success callback of the previous$.ajax
call. – War10ck Commented May 2, 2016 at 15:43 -
1
I agree. I thought about trying some type of method to slow down the requests to the server. I realize turning off
async
is deprecated in JQuery and would defeat the purpose anyway. Another method, using a library called Frame doesn't look like a good solution either, as it appears to no longer be maintained. – Joeventures Commented May 2, 2016 at 15:49 -
@Joeventures I've added an answer below that makes use of callbacks in a recursive nature to throttle the number of requests sent. In essence, it acts like
async: true
would but in a non-locking asynchronous state – War10ck Commented May 2, 2016 at 16:03
2 Answers
Reset to default 3I'm sure the following code still be optimized but here is a throttled approach:
$(document).ready(function() {
// Declare variable to hold data...
var results = [],
length = 0;
$("#popme").click(function(event) {
// Get Data
$.getJSON('/path/to/json_pids', function(data) {
// Store returned results in value accessible by all functions
results = data;
length = results.length;
$("#pop-result").html('<p>' + length + ' records</p>');
processItem();
});
});
function processItem() {
// Check length, if 0 quit loop...
if(results.length) {
// Make a call always referencing results[0] since we're shfiting the array results...
$.ajax({
url: '/path/to/json_student_info/' + results[0],
success: function() {
$("#pop-result").html('<p>' + ((length - results.length) + 1) + ' / ' + length + ' records</p>');
// Remove the first item to prepare for next iteration...
results.shift();
// Yay! for recursive functions...
processItem();
}
});
}
}
});
This should in theory, recursively call your service with the next item after the previous item has finished processing. In other words, it will make the operations seem synchronous as only one at a time will be processed, but it's using callbacks as oppose the the async
flag as you mentioned above that that flag is deprecated.
i so requested 5800 ajax at once and i have this Error
How I Fix it :
i set delay after 10 times of ajax and progress bar loading for user
You Can Change Times
Link 1: (stackoverflow.) Delay With Ajax
Link 2: (stackoverflow.) Use SetTimeout in For loop
here is code:
// Define this Function as Global | Link 1
var myAjaxConnection = function (param = null) {
$.ajax({ /* Your Config */});
}
// Define this Function as Global too | Link 2
function runTheTimeout(time, param = null){
setTimeout(function(){myAjaxConnection(param)}, time);
}
// My Code
arr = [1..5800]; // IMPORTANT: Your data
var timesLimit = 10;
for (var i = 0; i < arr.length; i++) {
var time = ((i % timesLimit ) == 0) ? 15000 : ((i % timesLimit ) * 300);
runTheTimeout(time); // You Can Send Param Too :]
}