为何先调用FileReader.readAsBinaryString再绑定事件仍能正常运行?
为什么先调用FileReader.readAsBinaryString再绑定事件处理函数仍能正常工作?
这事儿核心原因就两点:FileReader的读取操作是异步的,再加上JavaScript的单线程事件循环机制,让你反向写代码也能跑起来。
具体拆解下:
FileReader不会同步执行读取:当你调用
reader.readAsBinaryString(inputFile[0])时,浏览器并不会立刻开始读取文件并触发事件——它会把这个读取任务丢给后台线程处理,主线程则继续往下执行后面绑定onload和onerror的代码。事件循环的执行顺序:JavaScript主线程会先把当前Promise执行器里的所有同步代码跑完:先调用read方法,再完成两个事件处理函数的绑定。等后台的文件读取操作完成后,浏览器才会把
load或error事件加入事件队列,等主线程空闲时执行对应回调——这时候你的事件处理函数早就绑定好了,自然能正常触发。
不过要注意:虽然这段代码能正常运行,但规范写法还是应该先绑定事件处理函数,再调用read方法。现代浏览器里不会出问题,但理论上如果存在极端场景(比如读取的文件极小,后台线程在主线程还没绑定完事件就完成读取),可能会导致事件丢失——虽然实际中几乎遇不到,但遵循先绑定事件再触发操作的逻辑,代码会更健壮、可读性也更好。
修正后的规范写法:
const imgPromise = new Promise((resolve, reject) => { const reader = new FileReader(); // 先绑定事件处理函数 reader.onload = function(event) { resolve(); } reader.onerror = function() { reject(); } // 再调用读取方法 reader.readAsBinaryString(inputFile[0]); });
内容的提问来源于stack exchange,提问作者Alan Sanchez
相关产品推荐
相关产品推荐

