I tried researching about this matter, and I know that this error occurs because of too many ajax calls that's why the browser can't handle it. However I think that the solution is a case to case. Let me try to explain on how this code works
First I select a csv file (8000 rows) then I will upload it to the database, the calling function works like this.
$(document).on("click", "#btn-group-agent-upload", function () {
var reader = new FileReader();
updateUploadPercentage(0);
var file = $("#group-agent-file").prop("files")[0];
reader.readAsText(file, 'UTF-8');
reader.onload = Insert_Bulk_Agent;
});
and it execute the function Insert_Bulk_Agent
in which this
function Insert_Bulk_Agent(event) {
var result = event.target.result;
var data = $.csv.toObjects(result);
var length = data.length;
var count = 0;
var arrayCollection = [];
var tbody = $("#error-list").find("tbody");
if (length > 0) {
$.each(data, function (key, val) {
if(val.AgentStatus == "" || val.BirthDate == "" || val.CSP == "" || val.Classification == "" || val.ContactNumber == "" ||
val.EmailAddress == "" || val.FirstName == "" || val.LastName == "" || val.MiddleName == "" || val.LiveDate == "" || val.Program == "") {
$.ajax({
success: function () {
//console.log('ok');
$(tbody).append("<tr><td>" + val.FirstName + ' ' + val.MiddleName + ' ' + val.LastName + "</td>" +
"<td>" + val.Tool + "</td></tr>");
arrayCollection.push(val);
count = count + 1;
var percentageCompleted = count / length * 100;
updateUploadPercentage(parseInt(percentageCompleted));
}
});
} else {
$.ajax({
xhr: function () {
var xhr = $.ajaxSettings.xhr();
xhr.upload.onprogress = function (evt) {
count = count + 1;
var percentageCompleted = count / length * 100;
updateUploadPercentage(parseInt(percentageCompleted));
};
return xhr;
},
type: "POST",
url: "IROA_StoredProcedures.asmx/Insert_Bulk_Agent",
data: JSON.stringify(val),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function () {
},
error: function (XMLHttpRequest) {
count = count + 1;
var percentageCompleted = count / length * 100;
updateUploadPercentage(parseInt(percentageCompleted));
console.log(XMLHttpRequest);
console.log(JSON.stringify(val));
}
});
}
});
}
else {
alert("The selected file is empty");
}
Update_uam();
}
First
The function loop through each row and evaluates if the required fields are not null
or ""
value. If it is the function then add a row in a html
table. If it has values it will then call an ajax that will insert the values to the database. Now the issue is it's having problem because of multiple AJAX
calls. How can I handle this error?
Second
There is another function that wiill call here update_uam
is it sure that this function will execute after all the Insert_Bulk_Agent
process?
I tried researching about this matter, and I know that this error occurs because of too many ajax calls that's why the browser can't handle it. However I think that the solution is a case to case. Let me try to explain on how this code works
First I select a csv file (8000 rows) then I will upload it to the database, the calling function works like this.
$(document).on("click", "#btn-group-agent-upload", function () {
var reader = new FileReader();
updateUploadPercentage(0);
var file = $("#group-agent-file").prop("files")[0];
reader.readAsText(file, 'UTF-8');
reader.onload = Insert_Bulk_Agent;
});
and it execute the function Insert_Bulk_Agent
in which this
function Insert_Bulk_Agent(event) {
var result = event.target.result;
var data = $.csv.toObjects(result);
var length = data.length;
var count = 0;
var arrayCollection = [];
var tbody = $("#error-list").find("tbody");
if (length > 0) {
$.each(data, function (key, val) {
if(val.AgentStatus == "" || val.BirthDate == "" || val.CSP == "" || val.Classification == "" || val.ContactNumber == "" ||
val.EmailAddress == "" || val.FirstName == "" || val.LastName == "" || val.MiddleName == "" || val.LiveDate == "" || val.Program == "") {
$.ajax({
success: function () {
//console.log('ok');
$(tbody).append("<tr><td>" + val.FirstName + ' ' + val.MiddleName + ' ' + val.LastName + "</td>" +
"<td>" + val.Tool + "</td></tr>");
arrayCollection.push(val);
count = count + 1;
var percentageCompleted = count / length * 100;
updateUploadPercentage(parseInt(percentageCompleted));
}
});
} else {
$.ajax({
xhr: function () {
var xhr = $.ajaxSettings.xhr();
xhr.upload.onprogress = function (evt) {
count = count + 1;
var percentageCompleted = count / length * 100;
updateUploadPercentage(parseInt(percentageCompleted));
};
return xhr;
},
type: "POST",
url: "IROA_StoredProcedures.asmx/Insert_Bulk_Agent",
data: JSON.stringify(val),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function () {
},
error: function (XMLHttpRequest) {
count = count + 1;
var percentageCompleted = count / length * 100;
updateUploadPercentage(parseInt(percentageCompleted));
console.log(XMLHttpRequest);
console.log(JSON.stringify(val));
}
});
}
});
}
else {
alert("The selected file is empty");
}
Update_uam();
}
First
The function loop through each row and evaluates if the required fields are not null
or ""
value. If it is the function then add a row in a html
table. If it has values it will then call an ajax that will insert the values to the database. Now the issue is it's having problem because of multiple AJAX
calls. How can I handle this error?
Second
There is another function that wiill call here update_uam
is it sure that this function will execute after all the Insert_Bulk_Agent
process?
- 1 so, you're kicking off 8000 ajax requests all at once? – Jaromanda X Commented Jan 25, 2018 at 5:43
- yes. It depends on the file. But I tested it with 8000 rows. So its 8000 ajax request – Vian Ojeda Garcia Commented Jan 25, 2018 at 5:45
- The concept of triggering 8000+ requests should be reviewed. The final objective sure can be achieved another way. Relying on the client to mass query infos is a definitive Don't do!. – Louys Patrice Bessette Commented Jan 25, 2018 at 5:52
- 1 @JaromandaX your code works and I think the speed is great. The difference is not that long. Please post it as an answer so I can accept it. And if you have time can you please explain as much as you can on your available time. Thank you – Vian Ojeda Garcia Commented Jan 25, 2018 at 6:07
- 1 @LouysPatriceBessette yeah it's a rookie mistake so please give me a break :) – Vian Ojeda Garcia Commented Jan 25, 2018 at 6:07
1 Answer
Reset to default 4Firstly, here is a "multiple" queue I wrote (but never tested in production, so thanks for being the guinea pig :p )
This allows you to have a single "queue" to add Promises to, and they will end up in max
parallel queues - perfect for limiting the number of concurrent ajax requests. $.ajax
by the way, returns a Promise
Now, this is primitive, in that any error in one of the queue's will halt that queue, so it probably needs more to be properly useful
const multiQueue = max => {
max = (isNaN(max) || max < 1) ? 1 : max;
const q = new Array(max).fill(0).map(() => Promise.resolve());
let index = 0;
const add = (cb, ...args) => {
index = (index + 1) % max;
return (q[index] = q[index].then(() => cb(...args)));
};
return add;
};
I just had a quick think, and possibly
return (q[index] = q[index].then(() => cb(...args)
.then(data => ({data}))
.catch(error => ({error}))
);
may make the queues less fragile, note that all promises would then resolve to either
{data: whatever the resolved result was}
or{error: whatever the rejection reason was}
The changes to your code are minimal
Promise.all(data.map((val, key) => {
// inside the map function
})).then(Update_uam);
This will wait until all the Promises (ajax) are plete, then call Update_uam
inside the map function for either case of the condition
return queue(() => $.ajax({
// ajax request
}));
returns the promise returned by $.ajax
which has been added to the queue
So, the whole code is:
var queue = multiQueue(6); // most browsers I think limit to 6 simultaneous AJAX anyway
function Insert_Bulk_Agent(event) {
var result = event.target.result;
var data = $.csv.toObjects(result);
var length = data.length;
var count = 0;
var arrayCollection = [];
var tbody = $("#error-list").find("tbody");
if (length > 0) {
Promise.all(data.map((val, key) => {
if (val.AgentStatus == "" || val.BirthDate == "" || val.CSP == "" || val.Classification == "" || val.ContactNumber == "" ||
val.EmailAddress == "" || val.FirstName == "" || val.LastName == "" || val.MiddleName == "" || val.LiveDate == "" || val.Program == "") {
return queue(() => $.ajax({
success: function() {
//console.log('ok');
$(tbody).append("<tr><td>" + val.FirstName + ' ' + val.MiddleName + ' ' + val.LastName + "</td>" +
"<td>" + val.Tool + "</td></tr>");
arrayCollection.push(val);
count = count + 1;
var percentageCompleted = count / length * 100;
updateUploadPercentage(parseInt(percentageCompleted));
}
}));
} else {
return queue(() => $.ajax({
xhr: function() {
var xhr = $.ajaxSettings.xhr();
xhr.upload.onprogress = function(evt) {
count = count + 1;
var percentageCompleted = count / length * 100;
updateUploadPercentage(parseInt(percentageCompleted));
};
return xhr;
},
type: "POST",
url: "IROA_StoredProcedures.asmx/Insert_Bulk_Agent",
data: JSON.stringify(val),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function() {
},
error: function(XMLHttpRequest) {
count = count + 1;
var percentageCompleted = count / length * 100;
updateUploadPercentage(parseInt(percentageCompleted));
console.log(XMLHttpRequest);
console.log(JSON.stringify(val));
}
}));
}
})).then(Update_uam);
} else {
alert("The selected file is empty");
Update_uam();
}
}