TypeScript中FileReader readAsText异步遍历读取文件不等待问题
问题诱因
核心问题出在Array.forEach()的异步执行逻辑上:
forEach方法设计上不支持等待异步回调执行完成,你传入的async回调会被同步遍历触发,不会等待前一个回调内的await this.readFile()执行完成就进入下一轮循环,所有文件的读取操作会被并行发起,因此会出现先遍历完所有文件、触发所有readFile调用,之后才会陆续执行每个Promise完成后的console.log("next")的现象。- 你当前外层的
try/catch也无法捕获到文件读取过程中抛出的异常,因为forEach不会将异步回调的异常冒泡到外层作用域。
解决方案
要实现串行读取效果,只需要将forEach替换为支持await阻塞逻辑的普通for循环,同时将update函数声明为async即可,修改后的代码如下:
修改后的update函数
// 声明为async函数 async update(event){ console.log( event.target.files[0]) this.files = Array.from(event.target.files) try{ // 用普通for循环替代forEach实现串行等待 for (let index = 0; index < this.files.length; index++) { const file = this.files[index]; let last = index == this.files.length - 1; await this.readFile(file, last); console.log("next"); } // 若需要所有文件读取完成后统一执行后续逻辑,可直接在此处调用this.next(),无需在readFile内判断last标识 // this.next() } catch(e) { console.log(e) } }
可选优化(并行读取)
如果不需要严格按照顺序读取文件,想要提升读取效率,也可以用Promise.all一次性并行处理所有文件:
async update(event){ this.files = Array.from(event.target.files) try { const readPromises = this.files.map((file, index) => { return this.readFile(file, index === this.files.length - 1) }) await Promise.all(readPromises) console.log("所有文件读取完成") } catch(e) { console.log(e) } }
readFile逻辑补充说明
你当前readFile内的判断逻辑if(this.fileService.hasOwnProperty(tempName))是当服务类已存在对应属性时才读取文件内容,若你的预期是不存在该属性时才读取存储,可自行调整该判断条件,不影响异步逻辑的执行。
内容的提问来源于stack exchange,提问作者bitbytten
相关产品推荐
相关产品推荐

