I need to collect logs for different devices from a backend, to export it to a csv-file. Problem is the number of devices can vary. So I ask the backend for the amount of devices and loop through the requests for the logs.
The problem is the for...
loop runs too faster than I get the responses to $.post
, so the loop finishes before I get the responses. After some research I could handle that behaviour, but now I was asked to add data to the request, for which I have no reference to the according device is stored. So I added the device names and spots I need to poll in an external js-file, so I have a defined list to loop through.
I tried to use the index of the for loop to fetch the device names, which didn't work, since the loop was too fast. Now I have created a workaround, by defining a counter and pushing the devices in another variable. This doesn't feel "clean" and there should be a better way to poll the data and keep track for which device it is.
The code so far:
function collectData() {
var outString = "";
var lots of stuff I can pre-fetch
var logs = function (outString, saveCSV) {
var postString;
var devices = [];
var count = 0;
for (i = 1; i <= maxDevice; i++) {
postString = build postString in loop
devices.push(spots[0][i - 1]);
$.post('/path/foobar.db',
postString,
function (data) {
outString += "Spotlist for: " + spots[0][count] + "\n";
count++;
outString += data.replace(/{/g, "").replace(/}/g, "").replace(/:/g, ";").replace(/,/g, "\n").replace(/\"/g, "");
outString += "\n\n";
});
postString = "/path/eventlog.csv?device=" + i;
$.get(postString,
function (data) {
outString += "Event Log: \n" + data + "\n";
});
postString = "/path/errorlog.csv?device=" + i;
$.get(postString,
function (data) {
outString += "Error Log: \n" + data + "\n";
});
}
$(document).ajaxStop(function () {
saveCSV(outString, filename);
$(this).unbind('ajaxStop');
});
};
var saveCSV = function (outString, filename) {
var tempString = "data:text/csv;charset=utf-8," + outString;
var encodedUri = encodeURI(tempString);
var a = document.getElementById("dlLink");
if (window.navigator.msSaveOrOpenBlob) {
blobObject = new Blob([outString], {type: 'text/csv;charset=utf-8'});
window.navigator.msSaveBlob(blobObject, filename);
} else
{
a.setAttribute("href", encodedUri);
a.setAttribute("download", filename);
a.click();
}
};
outString = lots of predefined and pre-fetched stuff
outString += "Device data: \n\n";
logs(outString, saveCSV);
}
The part which I am not satisfied with is:
for (i = 1; i <= maxDevice; i++) {
postString = "get = {" + i + ":en:[";
for (j = 0; j < spots[i].length; j++) {
postString += '"' + spots[i][j] + '",';
}
postString = postString.slice(0, -1) + "]}";
devices.push(spots[0][i - 1]);
$.post('/path/foobar.db',
postString,
function (data) {
outString += "Spotlist for: " + spots[0][count] + "\n";
count++;
outString += data.replace(/{/g, "").replace(/}/g, "").replace(/:/g, ";").replace(/,/g, "\n").replace(/\"/g, "");
outString += "\n\n";
});
To output the device that I collected the spots for I use the counter, to track device names. I have the hunch this is not the best and "cleanest" method, so I'd like to ask if there is any better way to deal with the asynchronity (sp?) in terms of collecting the right device for which the post is made and also to trigger the DL if everything is done.
Since my question doesn't seem to be clear, perhaps I need to narrow it down. The code works, but it seems just to be tinkered by me and there should be cleaner ways to
A) handle the posts/gets, since the outstring for CSV is just put together in the way the requests are answered, so not device 1 is the first in the csv, but the one which comes first. $(document).ajaxStop
waits for everything to be finished, but not to be finished in the right order.
B) I need to relate the index of the for loop to the device I poll the data for. I used additional variables, that I count up to go through an additional array. Is there any better way?