FileReader读取Blob时状态永久停滞,求解决方案
针对你在Dart环境下使用MediaRecorder时,FileReader卡在loading状态、onload事件不触发的问题,给出以下实用修复思路:
直接替换FileReader,使用Blob原生的
arrayBuffer()方法
别再死磕FileReader了,Blob本身提供了返回Promise的arrayBuffer()方法,完全可以替代FileReader的读取逻辑,还能避开Dart编译器对JS事件处理的限制。
替换后的核心代码示例:// 废弃原FileReader逻辑 // const reader = new FileReader(); // reader.readAsArrayBuffer(event.data); // await reader.onloadend!(event); // const buffer = reader.result; // 改用Blob原生方法 const audioBuffer = await event.data.arrayBuffer();这个方法属于Web标准API,Dart的JS互操作层能更好地兼容,不会出现事件阻塞的问题。
排查Dart对JS事件绑定的限制
如果一定要保留FileReader,试试用addEventListener绑定事件,而非直接赋值onloadend属性——Dart编译器可能对后者的处理存在兼容性问题:const reader = new FileReader(); reader.addEventListener('loadend', (e) => { const buffer = e.target.result; // 后续音频处理逻辑 }); reader.readAsArrayBuffer(event.data);不过还是优先推荐Blob的
arrayBuffer(),代码更简洁且不易出问题。再次验证Blob的可读性
虽然你已确认MediaRecorder和Worklet输出正常,但可以快速验证Blob本身是否可读:在控制台执行event.data.size确认大小非0,或者尝试await event.data.text()(仅作验证,音频数据会乱码,但如果Promise能resolve,说明Blob本身没问题,问题确实出在FileReader的事件机制上)。规范Dart JS互操作的异步处理
如果你是通过dart:js库调用JS API,要确保将JS的Promise正确转换为Dart的Future,避免异步流程阻塞:import 'dart:js' as js; import 'dart:async'; // 假设event.data是JS Blob对象 js.JsObject audioBlob = ...; Future<ByteBuffer> getAudioBuffer() { return js.promiseToFuture<ByteBuffer>(audioBlob.callMethod('arrayBuffer', [])); }这种方式能让Dart正确处理JS的异步操作,不会出现永久阻塞的情况。
内容的提问来源于stack exchange,提问作者agustin bossi

