当前位置: 首页 > 知识库问答 >
问题:

在Javascript中同步读取文件

米迪
2023-03-14

我想读取一个文件,并使用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'变量的值?

共有3个答案

亢正德
2023-03-14

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

 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();
商俊智
2023-03-14

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

假设您的文件被破坏,HTML5API无法读取,它不会给出结果。它会破坏你的代码并封锁网站。或者,有人可以选择一个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);

检查功能,每秒检查就绪标志变量是否设置为true。如果是,您可以确定结果是可用的。

这可能不是最好的做法,这样做,但我做了一个webapp使用这种技术约30次与10多个setTimeout在同一时间运行,并经历了没有问题,直到现在。

姬成荫
2023-03-14

您可以使用标准FileReaderSync,它是FileReader API的一个更简单、同步、分块版本,与您已经使用的类似:

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

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

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

如果你需要一个主线程的解决方案,读起来像同步API,即顺序,你可以包装异步FileReader在一个promise和使用异步函数(你可能需要转置):

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

然后您可以在另一个异步上下文中等待此函数:

async function main() {
    let file = new File(...)
    let dataURL = await readFileAsDataURL(file)
    console.log(dataURL); // aGV5IHRoZXJl...
}

... 或者使用promise回调使用它(不需要异步上下文):

readFileAsDataURL(file).then(dataURL => {
    console.log(dataURL); // aGV5IHRoZXJl...
});
 类似资料:
  • 问题内容: 我一直在这样做,以便在Linux下同步读取整个stdin数据: 由于没有/ dev / stdin文件,因此这显然在Windows上不起作用。我该怎么做才能达到同样的目的? 问题答案: readline-sync模块可以很好地完成这项工作。 然后: https://www.npmjs.com/package/readline- sync

  • 问题内容: 阅读部分不是并发的,但处理是并发的。我用这种方式来命名标题,因为我最有可能使用该短语再次搜索此问题。:) 尝试 超越示例 之后,我陷入僵局,因此这对我来说是一种学习经验。我的目标是: 逐行读取文件(最终使用缓冲区执行多行)。 将文本传递给执行某些正则表达式的工作。 将结果发送到某个地方,但要避免使用互斥或​​共享变量。我正在将整数(总是数字1)发送到通道。这有点愚蠢,但是如果不引起问题

  • 我正面临这样一种情况: 现在,由于两个事务读取的是相同的整数值,因此此流会导致不正确的增量。 那么JPA实现中的悲观_写锁(Hibernate是我最感兴趣的一个)能防止这种流动吗? 该流是否属于脏读、不可重复读或幻象读的任何类别 在我看来不是因为 事务 2 在事务 1 写入(修改)之前读取数据,因此它不是脏读取 此处的事务中不会发生多次读取,因此不是不可重复读取或幻像读取的情况

  • 问题内容: 我试图将文本文件加载到我的JavaScript文件中,然后从该文件中读取行以获取信息,我尝试使用FileReader,但它似乎无法正常工作。有人可以帮忙吗? 问题答案: 是的,可以使用FileReader,我已经做了一个示例,这是代码: 最后,我只是读了其他一些吸引我的答案,但正如他们所建议的那样,您可能正在寻找使您能够从JavaScript文件所在的服务器(或设备)加载文本文件的代码

  • 问题内容: [编辑] 我使用 D3 解决了这个问题,不用了,谢谢! 所以我有一个看起来像这样的csv文件,我需要将本地csv文件导入到我的客户端javascript中: 我最终需要解析它并输出如下内容: 但就目前而言,我仍然只是将其导入javascript。 我当前的代码如下所示: 我已经研究并找到了一些关于的有用链接,但是我是javascript的新手,我并不完全了解它。我应该使用Ajax吗?F

  • 本文向大家介绍D3.js中强制异步文件读取同步的几种方法,包括了D3.js中强制异步文件读取同步的几种方法的使用技巧和注意事项,需要的朋友参考一下 发现问题 在使用d3.js时,我们经常会使用d3.csv()或者d3.json()函数来从文件中读取出数据,不幸的是,偶尔代码的结果并不是我们预料的那样。习惯了过程式编程的我开始的时候也是这样,最让人头疼的是javascript并不会告诉你问题出在哪里