Asynchronous execution in javascript any solution to control execution? - javascript

I need a solution to control code execution in javascript.I want code on next line should not be executed unless the code on current line is completely executed.
Is there any solution?
function handleFileSelect(evt) {
var files = evt.target.files;
for (var i = 0; i < files.length; i++) {
alert("for");
f = files[i];
fileExtension = f.name.split('.').pop();
if(fileExtension != 'kml' && fileExtension !='kmz' && fileExtension != 'csv'){
alert('Unsupported file type ' + f.type + '(' + fileExtension + ')');
return;
}
var fileReaderkmlcsv = new FileReader();
fileReaderkmlcsv.onloadend = loadend;
fileReaderkmlcsv.onerror = function(event) {
alert("ERROR: " + event.target.error.code);
};
fileReaderkmlcsv.readAsText(f);
} //- end for
} //handleFileSelect
function loadend(theFile) {
alert("loadend");
//code for processing my files
}

The issue is that loadend is running as soon as any one of the FileReaders has completed loading. You'll need to redesign the code to wait for all 3 of them to finish, something like:
function handleFileSelect(evt) {
var files = evt.target.files;
var fileReaders = [];
var loadCount = 0;
for (var i = 0; i < files.length; i++) {
f = files[i];
fileExtension = f.name.split('.').pop();
if(fileExtension != 'kml' && fileExtension !='kmz' && fileExtension != 'csv'){
alert('Unsupported file type ' + f.type + '(' + fileExtension + ')');
return;
}
function fileLoaded() {
loadCount++;
//Check if we've loaded all the files
if (loadCount == files.length) {
loadend(fileReaders);
}
}
var fileReaderkmlcsv = new FileReader();
fileReaderkmlcsv.onloadend = fileLoaded;
fileReaderkmlcsv.onerror = function(event) {
alert("ERROR: " + event.target.error.code);
};
fileReaderkmlcsv.readAsText(f);
fileReaders.push(fileReaderkmlcsv);
}
}
function loadend(files) {
//files now contains an array of completed FileReader objects
}
Note that I don't have direct experience of the FileReader object itself - if onloadend doesn't fire if an error occurs, you'll need to put similar logic in the onerror event as well to make sure that the loadCount variable still gets incremented/checked etc.

Related

JQuery FileReader onload not firing

I have a multiple file uploading. When I upload the images and binding to the model as follows not firing the FileReader onload function. It skip and fire remain
Here is my code
imageSelect: function (e) {
var dataModel = bindViewModel.selected.attachments;
var reader = new FileReader();
reader.onload = function () {
var uploadImg = new Image();
uploadImg.onload = function () {
for (var i = 0; i < e.files.length; i++) {
if (e.files[i].size < 1048576) {
var attachmentName = e.files[i].name;
var attachment = { id: i, citationId: bindViewModel.selected.id, attachmentName: attachmentName, attachmentUrl: reader.result };
dataModel.push(attachment);
if (dataModel[0].attachmentName == "" && dataModel[0].attachmentUrl == "") {
dataModel.splice($.inArray(dataModel[0], dataModel), 1);
}
uploadImg.src = reader.result;
reader.readAsDataURL(e.files[i].rawFile);
}
else {
app.ShowNotifications("Error", 'The ' + e.files[i].name + ' size greater than 1MB. \r\n Maximum allowed file size is 1MB.', "error");
}
}
};
};
}
Any one can have to help me?

Javascript filereader onload ( get file from server )

What I want is to read a file from the windows file system or a server so I can display the contents on the website and we are not allowed to use a database or PHP only Javascript.
What I currently have is beneath this and it works if I get the file from a html file upload box the only thing I need is how do I get a file in the javascript without inserting it manually but to load on pageload.
The rest of the code works if I insert the file manually I only need to get a file and insert it into var file = ;
var file = // How do I get file from windows system / or server is also a possibility
var reader = new FileReader();
reader.onload = function(progressEvent){
// Entire file
console.log(this.result);
// By lines
var lines = this.result.split('\n');
for(var line = 0; line < lines.length; line++){
console.log(lines[line]);
}
};
reader.readAsText(file);
I got it to work
var file = readTextFile("test.txt");
var allText;
var trumpCount = 0;
var hilaryCount = 0;
var reader = new FileReader();
// Entire file
console.log(this.result);
// alert(allText);
// By lines
var lines = allText.split('\n');
for(var line = 0; line < lines.length; line++){
// alert(lines[line]);
if (lines[line].indexOf("t") !== -1){
trumpCount++;
}else{
hilaryCount++;
}
}
alert("Votes for trump: " + trumpCount + " Votes for hilary: " + hilaryCount + " Total votes: " + (trumpCount + hilaryCount))
function readTextFile(file)
{
var rawFile = new XMLHttpRequest();
rawFile.open("GET", file, false);
rawFile.onreadystatechange = function ()
{
if(rawFile.readyState === 4)
{
if(rawFile.status === 200 || rawFile.status == 0)
{
allText = rawFile.responseText;
//alert(allText);
}
}
}
rawFile.send(null);
}

Read File byte for byte and parse to int

I have to read data from an file. This data was written by an server byte-wise into the file. The file has an fix structure, now I want to read the Information in it with JS.
I have found http://www.html5rocks.com/en/tutorials/file/dndfiles/ and copied it down to fiddle: http://jsfiddle.net/egLof4ph/
function readBlob(opt_startByte, opt_stopByte) {
var files = document.getElementById('files').files;
if (!files.length) {
alert('Please select a file!');
return;
}
var file = files[0];
var start = parseInt(opt_startByte) || 0;
var stop = parseInt(opt_stopByte) || file.size - 1;
var reader = new FileReader();
// If we use onloadend, we need to check the readyState.
reader.onloadend = function(evt) {
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
document.getElementById('byte_content').textContent = evt.target.result;
document.getElementById('byte_range').textContent = ['Read bytes: ', start + 1, ' - ', stop + 1,
' of ', file.size, ' byte file'].join('');
}
};
var blob = file.slice(start, stop);
var a = reader.readAsBinaryString(blob);
}
document.querySelector('.readBytesButtons').addEventListener('click', function(evt) {
if (evt.target.tagName.toLowerCase() == 'button') {
var startByte = evt.target.getAttribute('data-startbyte');
var endByte = evt.target.getAttribute('data-endbyte');
readBlob(startByte, endByte);
}
}, false);
I knew that the first 7 Bytes are crap and can throw them away. The next 68Bytes belong together and every value is 4bytes big. After the 68Bytes again 68 usable bytes come (that 68bytes are "timeslots").
My Question:
When I am using that Code I get many signs (A, Q, &&&, special chars,..), but the data are in reality longs. How can I parse them into Numbers? According to the Filereader API readAsBinarsString() returns raw binary data. And how to correctly parse the whole File?
So, the original File looks like this:
<7B>Metadata</7B><4B>long value</4B>....17times for each timeslot <4B>long value</4B>....17times again.... and this util the end of the file.
When I am using the above Code I get output like: �&�&WK��
Furthermore I have found: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays (since FileReader provides an method which returns an ArrayBuffer), so I guess I should use readAsArrayBuffer(), but how to use it to get to my data?
You really need binary ?
Note that readAsBinaryString method is now deprecated as per the 12 July 2012 Working Draft from the W3C.
function readBlob(opt_startByte, opt_stopByte) {
var files = document.getElementById('files').files;
if (!files.length) {
alert('Please select a file!');
return;
}
var file = files[0];
var start = parseInt(opt_startByte) || 0;
var stop = parseInt(opt_stopByte) || file.size - 1;
var reader = new FileReader();
reader.onloadend = function (evt) {
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
var a = new Uint8Array(evt.target.result)
var binary = ""
for (var i =0; i <= a.length; i++) {
binary += Number(a[i]).toString(2)
}
document.getElementById('byte_content').textContent = binary;
document.getElementById('byte_range').textContent = ['Read bytes: ', start + 1, ' - ', stop + 1,
' of ', file.size, ' byte file'].join('');
}
};;
var blob = file.slice(start, stop);
var a = reader.readAsArrayBuffer(blob)
}
document.querySelector('.readBytesButtons').addEventListener('click', function (evt) {
if (evt.target.tagName.toLowerCase() == 'button') {
var startByte = evt.target.getAttribute('data-startbyte');
var endByte = evt.target.getAttribute('data-endbyte');
readBlob(startByte, endByte);
}
}, false);

How do I loop through a file, byte by byte, in JavaScript?

I need some help getting my head around how the file is accessed in JavaScript to do some operations on it.
I would like to loop through a file byte by byte using JavaScript.
I can already select which file I would like to read. And I can read preset byte of the file.
I've found this nice example on how to read a slice of a file here:
http://www.html5rocks.com/en/tutorials/file/dndfiles/
Here is the snippet of code which I'm playing with:
<style>
#byte_content {
margin: 5px 0;
max-height: 100px;
overflow-y: auto;
overflow-x: hidden;
}
#byte_range { margin-top: 5px; }
</style>
<input type="file" id="files" name="file" /> Read bytes:
<span class="readBytesButtons">
<button data-startbyte="0" data-endbyte="4">1-5</button>
<button data-startbyte="5" data-endbyte="14">6-15</button>
<button data-startbyte="6" data-endbyte="7">7-8</button>
<button>entire file</button>
</span>
<div id="byte_range"></div>
<div id="byte_content"></div>
<script>
function readBlob(opt_startByte, opt_stopByte) {
var files = document.getElementById('files').files;
if (!files.length) {
alert('Please select a file!');
return;
}
var file = files[0];
var start = parseInt(opt_startByte) || 0;
var stop = parseInt(opt_stopByte) || file.size - 1;
var reader = new FileReader();
// If we use onloadend, we need to check the readyState.
reader.onloadend = function(evt) {
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
document.getElementById('byte_content').textContent = evt.target.result;
document.getElementById('byte_range').textContent =
['Read bytes: ', start + 1, ' - ', stop + 1,
' of ', file.size, ' byte file'].join('');
}
};
var blob = file.slice(start, stop + 1);
reader.readAsBinaryString(blob);
}
document.querySelector('.readBytesButtons').addEventListener('click', function(evt) {
if (evt.target.tagName.toLowerCase() == 'button') {
var startByte = evt.target.getAttribute('data-startbyte');
var endByte = evt.target.getAttribute('data-endbyte');
readBlob(startByte, endByte);
}
}, false);
</script>
Now I would like to loop through the file, four bytes at a time, but cannot seem to figure out how to do that. The reader does not seem to allow me to read more than once.
Once I can read from the file more than once, I should be able to iterate through it quite easily with something like this:
while( placemark != fileSize-4 ){
output = file.slice(placemark, placemark + 4);
console.log(output);
placemark = placemark + 5;
}
Thanks in advance!
Here is a link to a jsFiddle and plnkr version
I'm not sure it is what you wanted but maybe it can help, and anyway I had fun.
I tried setting reader and file vars as global :
var reader = new FileReader(), step = 4, stop = step, start = 0, file;
document.getElementById('files').addEventListener('change', load, true);
function load() {
var files = document.getElementById('files').files;
file = files[0];
reader.onloadend = function(evt) {
if (evt.target.readyState == FileReader.DONE) {
var result = evt.target.result;
document.getElementById('byte_content').textContent += result;
document.getElementById('byte_range').textContent = ['Read bytes: ', start, ' - ', start+result.length,
' of ', file.size, ' byte file'
].join('');
}
}
}
function next() {
if (!file) {
alert('Please select a file!');
return;
}
var blob = file.slice(start, stop);
reader.readAsBinaryString(blob);
start+= step;
stop = start+step;
}
function loop() {
if (!file) {
alert('Please select a file!');
return;
}
if (start < file.size) {
next();
setTimeout(loop, 50);
}
}
<input type="file" id="files" name="file" />Read bytes:
<span class="readBytesButtons">
<button onclick="next()">next</button>
<button onclick="loop()">loop</button>
</span>
<div id="byte_range"></div>
<div id="byte_content"></div>
I'd read the blob as an ArrayBuffer and use a DataView to read through the data
function readBlob(opt_startByte, opt_stopByte) {
var files = document.getElementById('files').files;
if (!files.length) {
alert('Please select a file!');
return;
}
var file = files[0];
var start = parseInt(opt_startByte) || 0;
var stop = parseInt(opt_stopByte) || file.size - 1;
var reader = new FileReader();
reader.onload = function(evt) {
var placemark = 0, dv = new DataView(this.result), limit = dv.byteLength - 4, output;
while( placemark <= limit ){
output = dv.getUint32(placemark);
console.log(' 0x'+("00000000" + output.toString(16)).slice(-8));
placemark += 4;
}
};
var blob = file.slice(start, stop + 1);
reader.readAsArrayBuffer(blob);
}
<input type="file" id="files" onchange="readBlob(0, 100)">
In the onload handler of FileReader, convert the result to string (toString()), then read 4 chars at a time with the string's slice method.
var contents = null;
reader.onload = function(){
contents = reader.result.toString();
}
var startByte = 0;
// read 4 bytes at a time
var step = 4;
// actual reading (doesn't alter the contents object)
console.log(contents.slice(startByte, step))
// update the next startByte position
startByte += step;

javaScript file loads in wrong order

I'm new to javaScript and am trying to load a CSV or TXT file into the browser.
When the file is selected an event handler displays the file name and details, once the user hits the load button the script should double check the file extension, load the file then carry out some further checks on the file.
My problem is that the file load function seems to always be called last meaning the other checks happen first.
The file is held here: http://bananamountain.net/project/20140703pm/file-loader2.html
Code pasted below:
</head>
<body>
<script>
// Check for the various File API support.
if (window.File && window.FileReader && window.FileList && window.Blob) {
// Great success! All the File APIs are supported.
} else {
alert('The File APIs are not fully supported in this browser.');
}
</script>
<h3>File Load test</h3>
<p>Use only test-data-csv.csv just now</p>
<input type="file" id="file" name="file" required="required" accept=".csv, .txt" />
<button onclick="handleFileLoad()">Load button</button>
<output id="list"></output>
<script>
// global variables
var content;
var fileName;
var splitString = ",";
var rows = new Array();
var headerRow = new Array();
var values = new Array();
function handleFileLoad() {
//var suitableFileType = checkFileType();
//document.write("<strong>Suitable file type: " + suitableFileType + "</strong><br />");
loadFile();
var suitableContent = checkFileContent();
document.write("<strong>Suitable file content: " + suitableContent + "</strong><br />");
}
function checkFileType() {
document.write("inside checkFileType<br/>");
// var testFile = fileName.split(".")[1].toUpperCase();
// document.write("file extension is '" + testFile+ "'<br />");
if ((fileName.split(".")[1].toUpperCase() === "CSV")) {
document.write('suitable file selected<br/>');
return (true);
} else if (fileName.split(".")[1].toUpperCase() === "TXT") {
document.write('suitable file selected<br/>');
return (true);
}else {
document.write('Invalid file format! \nPlease select a suitable .txt or .csv file<br/>');
return (false);
}
} // end of checkFileType - tested WORKING
function loadFile() {
// checkFileType();
var file = document.getElementById("file").files[0];
var reader = new FileReader();
var link_reg = /(http:\/\/|https:\/\/)/i;
reader.onload = function(file) {
// content = reader.result;
content = file.target.result;
rows = file.target.result.split(/[\r\n|\n]+/);
for (var i=0; i<rows.length; i++) {
document.write("row found at line " + i + " is " + rows[i] +".<br/>");
}
};
reader.readAsText(file);
/*
var suitableFileType = checkFileType();
document.write("<strong>Suitable file type: " + suitableFileType + "</strong><br />");
var suitableContent = checkFileContent();
document.write("<strong>Suitable file content: " + suitableContent + "</strong><br />");
var splitStringFound = getSplitString();
document.write("<strong>Split string found: " + splitStringFound + "</strong><br />");
document.write("<strong>Split String: " + splitString + "</strong><br/>");
var replacedHeaders = checkHeaderRow();
document.write("<strong>Header row complete<br />" + replacedHeaders +" headers replaced</strong><br/>");
document.write(content);
document.write(fileName);
document.write(splitString);
document.write(rows);
document.write( headerRow);
document.write(values);*/
return;
}
function checkFileContent() {
document.write("inside check file content<br/>");
// check for file content
// identifies blank lines and deletes them
// checking content of rows
for (var i=0;i<rows.length;i++) {
document.write ("Row " + i + " is " + rows[i]);
}
var filteredArr = rows.filter(function (val) {
return !(val === "" || typeof val == "undefined" || val === null || val === ",," || val === "\t\t");
});
// identifies empty file (e.g. all blank lines deleted)
if (filteredArr.length === 0) {
document.write("Empty file - no data found <br/>");
rows = filteredArr;
return false;
// check for row deletions
} else if (rows.length < filteredArr.length) {
rows = filteredArr;
document.write("blank rows deleted - " + (rows.length - filteredArr.length) + " rows remaining. <br/>");
return ("deletions");
} else {
document.write("No blank rows <br/>");
return true;
}
} // end of check file content - empty file tested, file with one line tested
function checkHeaderRow() {
// check for header row
// words in first non-empty row
var replaceCount = 0;
var checkArray = rows[0].split(splitString);
for (var i = 1; i < checkArray.length; i++) {
// start at array[1] as array[0] not likely to be a header value
// loop through inserting non numeric values into headerRow array
if (isNaN(checkArray[i])) {
headerRow[i - 1] = checkArray[i];
// need a flag to remove this from file once it has been done
replaceCount++;
} else {
headerRow[i - 1] = "Risk " + i;
}
}
// if non numeric values in array[1] delete rows[0]
// so the header row is not included with the data set
if (isNaN(checkArray[1])) {
rows[0] = null;
}
return (replaceCount);
} // end of checkHeaderRow works for all non-numeric, all numeric and mixed
function getSplitString() {
// call countCharacter to return count of comma and tab characters in first five lines
var tabCount = countCharacter("\t");
var commaCount = countCharacter(",");
// compare tabCount and commaCount values
if (tabCount === 0 && commaCount === 0) {
document.write("Cannot detect the value seperator,\n please ammend file to seperate values with tabs or commas");
return false;
}
else if (tabCount === commaCount) {
splitString = prompt("Cannot detect the value seperator,\n please input \"\\t\" for tabs or \",\" for commas");
if ((splitString === null) || (splitString != '\t') || (splitString != ',')) {
document.write("please check file and try again<br/>");
splitString = ',';
return false;
} // NOT WORKING
else {
return true;
}
} else if (tabCount>commaCount) {
splitString = "\t";
if (commaCount!=0) {
document.write("tab character selected as value seperator.<br/>");
// alert as this may not be the case
}
return true;
} else {
splitString=",";
if (tabCount!=0){
document.write("tab character selected as value seperator.<br/>");
// alert as this may not be the case
}
return true;
}
} // end of getSplitString - NOT FULLY WORKING
function splitRows() {
// what if rows is now empty? (e.g. header row only in file)
if (rows[0] != null) {
for (var i=0; i<rows.length;i++) {
values.push(rows[i].split(splitString));
}
return values;
} else {
return false;
}
} // end of splitRows fully working
function checkEmptyCells () {
for (var i=0; i<values.length; i++) {
for (var j=0; j<values[i].length; j++)
if (!((values[i][j] === "") || (typeof values[i][j] == "undefined") || (values[i][j] === null) || (values[i][j] === ",,") || (values[i][j] === "\t\t"))) {
// remove line values[i][j]
document.write("in here");
}
}
} // NOT FININSHED - STOPPED HERE
function countCharacter (character) {
// count the instances of a specified character over first 5 lines (or length of rows array)
// number of rows to loop through
var loopCount=0;
var characterCount=0;
if (rows.length < 5) {
loopCount = rows.length;
} else {
loopCount = 5;
}
for (var count=0; count < loopCount; count++) {
characterCount += rows[count].split(character).length-1;
}
return characterCount;
} // End of countCharacter - WORKING - TESTED
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
// files is a FileList of File objects. List some properties.
var output = [];
for (var i = 0, f; f = files[i]; i++) { // THIS IS NOT NEEDING TO BE IN A LOOP
output.push('<strong>', escape(f.name), '</strong> ', ' - ',
f.size, ' bytes, last modified: ',
f.lastModifiedDate ? f.lastModifiedDate.toLocaleDateString() : 'n/a',
'');
fileName = escape(f.name);
}
document.getElementById('list').innerHTML = '<div class="file-name">' + output.join('') + '</div>';
}
document.getElementById('file').addEventListener('change', handleFileSelect, false);
</script>
</body>
</html>
So first of all I think I asked the question wrong and it was for that reason that there were limited responses. I'm adding the answer so that if anyone has the same issue and comes across this that it can help them.
The problem was not in the html file loading but a file being loaded through javascript. The script carried out some checks on the file, loaded the file and then carried out further checks on the contents of the file.
This was all happening correctly however javascript does a thing called asyncronious loading where it calls the functions in turn but moves to the next function before the current function has finished doing what it is doing.
Imagine you go to a bar, order drinks, pay for your drinks and go to your table. Javascript would do this but without the normal pauses of waiting to get served, the useing of the drinks and getting change.
Essentially my code was going back to the table without drinks (or checking the contents of the file without it finishing loading).
To fix it I put a time out in, this probably isn't the best as the load speed will depend on the size of the file. However it works for just now and allows me to get on with other stuff.
A snippet of the working code is as follows:
{
function handleFileLoad() {
if (checkFileType()) {
values = [];
loadFile();
} else {
alert("Invalid file format! \nPlease select a suitable .txt or .csv file<br/>");
return;
}
//setTimeout(fileContentChecks(), 1000);
if (!setTimeout(fileContentChecks(), 1000)) {
return;
} else {
setData(); //PROBABLY PUT THESE IN A FUNCTION OR TWO
setComboLists(); //SO THESE CAN BE CALLED LATER TO UPDATE PAGE
UpdateAssetList();
UpdateXAxisList();
UpdateYAxisList();
UpdateTable();
}
}
function checkFileType() { // CHECK FILE NAME EXTENSION
if ((fileName.split(".")[1].toUpperCase() === "CSV")) {
return (true);
} else if (fileName.split(".")[1].toUpperCase() === "TXT") {
return (true);
} else {
return (false);
}
} // end of checkFileType - tested WORKING
function loadFile() { // LOADS FILE AND SPLITS INTO ROWS
var file = document.getElementById("file").files[0];
var reader = new FileReader();
var link_reg = /(http:\/\/|https:\/\/)/i;
reader.onload = function(file) {
content = file.target.result;
rows = file.target.result.split(/[\r\n|\n]+/);
};
reader.readAsText(file);
// NEEDS TIMEOUT HERE.....
return;
} // end of loadFile - TESTED WORKS WHEN STEPPING THROUGH - NEEDS TIMEOUT
function fileContentChecks() {
if (checkFileContent()) {
if (getSplitString()) {
checkHeaderRow();
} else {
alert("Seperator value not found"); // not sure if this is required?
return false;
}
} else {
alert("File contents not verified, please check file and try again.");
return false;
}

Categories

Resources