Async函数FileReader问题:数组打印正常但length属性为0
问题根因
出现这个现象是两个逻辑问题共同导致的:
FileReader.readAsText()本身是事件驱动的异步API,不返回Promise,你在代码里写的await reader.readAsText(blob)没有任何等待效果,外层await parseFile()执行到return的时候,文件分块读取流程根本没执行完,此时ansList还是空数组,所以打印ansList.length得到0。- 控制台打印引用类型值时是懒加载的:你看到打印出来的数组展开后有内容,是因为你手动在控制台展开数组的时候,异步读取流程已经跑完、哈希值已经被push进数组了,不是
console.log执行的那一刻数组里就有值。
修复方法
把整个分块读取逻辑用Promise包装,只有当所有分块读取完成、哈希计算结束后才把结果resolve出去,保证await能等到真实的返回值:
async function parseFile(file, type) { const fileSize = file.size; const chunkSize = 1024 * 1024; // 单块大小1MB let offset = 0; const hash = sha1.create(); const ansList = []; return new Promise((resolve, reject) => { const readEventHandler = async function (evt) { if (evt.target.error) { console.log('Read error: ' + evt.target.error); reject(evt.target.error); return; } offset += evt.target.result.length; await hash.update(evt.target.result); if (offset >= fileSize) { const ans = await hash.hex(); console.log(ans); ansList.push(ans); if (type.localeCompare('multiple') === 0) { filesUploadHashes.PostFiles.push(ans); } else { filesUploadHashes.Thumbnail.push(ans); } resolve(ansList); return; } chunkReaderBlock(offset, chunkSize, file); }; const chunkReaderBlock = function (_offset, length, _file) { const reader = new FileReader(); const blob = _file.slice(_offset, length + _offset); reader.onload = readEventHandler; reader.onerror = err => reject(err); reader.readAsText(blob); }; // 启动第一块读取 chunkReaderBlock(offset, chunkSize, file); }); }
补充提示:如果要计算非文本文件(图片、视频、压缩包等)的哈希,不要用
readAsText(),会因为文本编码转义导致哈希值计算错误,替换成readAsArrayBuffer()即可。
内容的提问来源于stack exchange,提问作者Sukhamjot Singh
相关产品推荐
相关产品推荐

