I'm uploading a CSV file to the server, then in the backend I split that file into multiple smaller files (because these files can get quite big). After uploading and splitting the file, I then want to process the file to insert some new data to the database.
All the logic works properly, however, I need to run some cleanup code after all files have finished processing. After researching for a while I found that I can make this happen by using Javascript promises.
I have always had problems understanding Javascript promises, it's the second night in a row that I stay up until past midnight to try and get this finished, so I don't think my understanding of Javascript promises will improve that much this soon, I just need to get this done.
Anyone with experience in Javascript promises, can you see what I'm doing wrong or what I'm missing? My code below is quite explanatory (I think).
function sendAjaxRequest(data, callback, addUploadEvents = false) {
return new Promise(function (resolve, reject) {
let xhr = new XMLHttpRequest();
xhr.open('POST', ajaxurl);
// when finished, we run our passed callback
xhr.onload = callback;
// only when uploading the file
if ( addUploadEvents ) {
xhr.addEventListener('loadstart', function() {
console.log('uploading file');
});
xhr.addEventListener('progress', function(evt) {
console.log('loaded: ' + evt.loaded + ', total: ' + evt.total);
});
xhr.addEventListener('loadend', function() {
console.log('file uploaded');
});
}
// general events to catch errors
xhr.addEventListener('timeout', function(e) {
console.log('the request has timed out', e);
reject(e);
});
xhr.addEventListener('error', function(e) {
console.log('the request returned an error', e);
reject(e);
});
xhr.addEventListener('abort', function(e) {
console.log('the request was aborted', e);
reject(e);
});
// send the request
xhr.send(data);
});
}
function uploadFile() {
let data = new FormData(),
f = document.querySelector('form [name="csv"]').files;
data.append('csv', f[0]);
// send the request
let req = sendAjaxRequest(data, function() {
if ( this.status === 200 ) {
const response = JSON.parse(this.response);
if ( ! response.success ) {
console.log('error in the uploadFile request');
return false;
}
// once the file is uploaded, we want to split it into several smaller pieces
splitToMultipleFiles();
}
else {
// should not reach this ever, I think I covered all problematic cases
console.log('there was an error in the request', this);
}
}, true);
// returning false to prevent the form from reloading the page
return false;
}
function splitToMultipleFiles() {
let data = new FormData();
// send the request
let req = sendAjaxRequest(data, function() {
if ( this.status === 200 ) {
const response = JSON.parse(this.response);
if ( ! response.success ) {
console.log('error in the splitToMultipleFiles request');
return;
}
// response.data.files has an array of files I want to process in the backend one at a time
let processingFiles = response.data.files.map(function(file) {
return processFile(file);
});
// wait until all files have been processed, then run some cleanup logic
// the problem is, the promises are never resolved :(
Promise.all(processingFiles).then(function() {
console.log('all done, cleanup your mess');
});
}
});
}
function processFile(tempFile) {
let data = new FormData();
data.append('temp-file', tempFile);
// send the request
return sendAjaxRequest(data, function() {
if ( this.status === 200 ) {
const response = JSON.parse(this.response);
if ( ! response.success ) {
console.log('error in the processFile request for file ' + tempFile);
return;
}
console.log('file finished processing: ' + tempFile);
}
});
}