在Javascript中同步读取文件

时间:2013-06-12 14:51:54

标签: javascript html5 filereader

我想读取一个文件,并使用FileReader对象将其转换为base64编码的字符串。这是我使用的代码:


    var reader = new FileReader();
    reader.onloadend = function(evt) {  
        // file is loaded
        result_base64 = evt.target.result; 
    };
    reader.readAsDataURL(file); 


但在这种情况下,我在事件处理程序(onLoadEnd事件)中获得转换结果。我想要一个同步方法。有没有办法“readAsDataURL”方法可以直接返回'result_base64'变量的值?

由于

7 个答案:

答案 0 :(得分:17)

同步任务(阻塞)通常很糟糕。如果没有真正的理由异步执行此操作,我强烈建议您使用事件回调。

想象一下你的文件坏了,HTML5无法读取,它不会给你结果。它会破坏您的代码并阻止该网站。或者,有人可以选择一个10GB的文件,这会冻结您的HTML页面,直到文件完全加载。使用该异步事件处理程序,您可以捕获可能的错误。

要解决回调的限制,我使用一个简单的技巧:

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);

check函数,每秒检查ready标志变量是否设置为true。如果是这样,您可以确定结果可用。

这可能不是最好的做法,但我使用这种技术制作了一个webapp大约30次,同时运行超过10个setTimeout,直到现在都没有遇到任何问题。

答案 1 :(得分:1)

要同步读取文件的内容,请使用fs.readFileSync

var fs = require('fs');
var content = fs.readFileSync('myfilename');
console.log(content);

fs.createReadStream创建一个ReadStream

答案 2 :(得分:1)

您可以使用标准的FileReaderSync,它是FileReader API的更简单,同步的阻止版本,类似于您已经在使用的版本:

let reader = new FileReaderSync();
let result_base64 = reader.readAsDataURL(file); 

console.log(result_base64); // aGV5IHRoZXJl...

请记住,尽管出于明显的原因,这仅在工作线程中可用。


如果您需要一个“类似于”同步API的主线程解决方案,则可以将async FileReader包装在promise中并使用async函数(您可能需要转换):

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...
}

答案 3 :(得分:0)

以下代码以同步方式读取文件

 function SyncFileReader(file) {
    let self = this;
    let ready = false;
    let result = '';

    const sleep = function (ms) {
      return new Promise(resolve => setTimeout(resolve, ms));
    }

    self.readAsArrayBuffer = async function() {
        while (ready === false) {
          await sleep(100);
        }
        return result;
    }    

    const reader = new FileReader();
    reader.onloadend = function(evt) {
        result = evt.target.result;
        ready = true;
    };
    reader.readAsArrayBuffer(file);
  }

用法:

const fileReader = new SyncFileReader(file);
const arrayBuffer = await fileReader.readAsArrayBuffer();

答案 4 :(得分:0)

以下代码以同步方式读取文件并以文本(字符串)形式返回其内容

 function SyncFileReader(file) {
    let self = this;
    let ready = false;
    let result = '';

    const sleep = function (ms) {
      return new Promise(resolve => setTimeout(resolve, ms));
    }

    self.readAsDataURL = async function() {
        while (ready === false) {
          await sleep(100);
        }
        return result;
    }    

    const reader = new FileReader();
    reader.onloadend = function(evt) {
        result = evt.target.result;
        ready = true;
    };
    reader.readAsDataURL(file);
  }

用法:

const fileReader = new SyncFileReader(file);
const arrayBuffer = await fileReader.readAsDataURL();

答案 5 :(得分:-2)

在Node.js中,使用execSync中的child_process并让shell同步读取它。将此子进程的输出重定向到父进程。

// 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();

我很乐意接受你的UUOC奖提名。 ;)

答案 6 :(得分:-8)

在业务的后期,但可能这将有助于某人。我们可以简单地把战斗带到房间外面。

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];
    }
}