问题
I would like to read a file and convert it into a base64 encoded string using the FileReader object. Here's the code I use :
var reader = new FileReader();
reader.onloadend = function(evt) {
// file is loaded
result_base64 = evt.target.result;
};
reader.readAsDataURL(file);
But in this case, I get the result of the conversion in the event handler (onLoadEnd event). I would like a synchronous method. Is there a way the "readAsDataURL" method can return directly the value of the 'result_base64' variable ?
Thanks
回答1:
Synchronous tasks (blocking) are generally bad. If there is no real reason to do that asynchronously, I strongly recommend you to use the event callback.
Imagine your file is broken and the HTML5 api cant read, it wont give you the result. It would break your code and block the site. Or, someone could select a 10GB file, which would freeze your HTML page until the file is completely loaded. With that asynchronous event handler your able to catch possible errors.
To work around limitations with callbacks, i use a simple trick:
var ready = false;
var result = '';
var check = function() {
if (ready === true) {
// do what you want with the result variable
return;
}
setTimeout(check, 1000);
}
check();
var reader = new FileReader();
reader.onloadend = function(evt) {
// file is loaded
result = evt.target.result;
ready = true;
};
reader.readAsDataURL(file);
the check function, checks every second if the ready flag variable is set to true. If so, you can be sure the result is available.
It may not be best practice to do so, but i made a webapp using this technique about 30 times with more than 10 setTimeouts at the same time running, and experienced no problem until now.
回答2:
You can use the standard FileReaderSync, which is a simpler, synchronous, blocking version of the FileReader API, similar to what you are already using:
let reader = new FileReaderSync();
let result_base64 = reader.readAsDataURL(file);
console.log(result_base64); // aGV5IHRoZXJl...
Keep in mind though that this is only available in worker threads, for obvious reasons.
If you need a solution for the main thread that "reads like" a synchronous API, you can wrap the async FileReader in a promise and use async functions (you might need to transpile):
async function readFileAsDataURL(file) {
let result_base64 = await new Promise((resolve) => {
let fileReader = new FileReader();
fileReader.onload = (e) => resolve(fileReader.result);
fileReader.readAsDataURL(file);
});
console.log(result_base64); // aGV5IHRoZXJl...
return result_base64;
}
回答3:
To read the contents of a file synchronously use fs.readFileSync
var fs = require('fs');
var content = fs.readFileSync('myfilename');
console.log(content);
fs.createReadStream creates a ReadStream.
回答4:
In Node.js, Use execSync from child_process and have the shell read it in for you synchronously. Redirect the output of this child process to the parent.
// Don't forget to use your favorite encoding in toString()
var execSync = require('child_process').execSync;
var fileContents = execSync('cat path/to/file.txt', {stdio: "pipe"}).toString();
I'll gladly accept your nomination for the UUOC award. ;)
回答5:
Late in the business, but may be this will help someone. We can just simply take the fight outside of the room.
var file = $('#myfile')[0].files[0];
var reader = new FileReader();
reader.onload = function(progressEvent) {
//console.log(this.result);
handle(this.result);
};
reader.readAsText(file);
function handle(temp_lines) {
var inputLines=new Array();
var lines = temp_lines.split('\n');
for(var line = 0; line < lines.length; line++) {
console.log(lines[line]);
inputLines[line]=lines[line];
}
}
来源:https://stackoverflow.com/questions/17068610/read-a-file-synchronously-in-javascript