FileReader
的使用机会很多,但是它是异步的,因此很容易出现回调地狱。
我们可以使用async/await特性,它允许我们以同步的方式调用异步代码。
封装成方法
export async function readTextFile(file: File) { const reader = new FileReader(); reader.readAsText(file); return new Promise((resolve, reject) => { reader.onload = () => resolve(reader.result); reader.onerror = () => reject(reader.error); }); } export async function readBinaryFile(file: File) { const reader = new FileReader(); reader.readAsArrayBuffer(file); return new Promise((resolve, reject) => { reader.onload = () => resolve(reader.result); reader.onerror = () => reject(reader.error); }); } export async function readAsText(file: File) { const reader = new FileReader(); reader.readAsText(file); return new Promise((resolve, reject) => { reader.onload = () => resolve(reader.result); reader.onerror = () => reject(reader.error); }); }
使用方法:
(async()=> { const buffer1 = await readTextFile(file); const buffer2 = await readBinaryFile(file); const buffer3 = await readAsText(file); })();
Javascript封装成一个class
class FileReaderEx extends FileReader{ constructor(){ super(); } #readAs(blob, ctx){ return new Promise((res, rej)=>{ super.addEventListener("load", ({target}) => res(target.result)); super.addEventListener("error", ({target}) => rej(target.error)); super[ctx](blob); }); } readAsArrayBuffer(blob){ return this.#readAs(blob, "readAsArrayBuffer"); } readAsDataURL(blob){ return this.#readAs(blob, "readAsDataURL"); } readAsText(blob){ return this.#readAs(blob, "readAsText"); } }
使用方法:
(async()=>{ const buffer1 = await new FileReaderEx().readAsArrayBuffer(blob1); const buffer2 = await new FileReaderEx().readAsDataURL(blob2); const buffer3 = await new FileReaderEx().readAsText(blob3); })();
TypeScript封装成一个class
export class FileReaderEx extends FileReader { constructor() { super(); } private readAs(blob: Blob, ctx: 'readAsArrayBuffer' | 'readAsDataURL' | 'readAsText') { return new Promise((res, rej) => { super.addEventListener("load", ({target}) => res(target?.result)); super.addEventListener("error", ({target}) => rej(target?.error)); super[ctx](blob); }); } readAsArrayBuffer(blob: Blob) { return this.readAs(blob, "readAsArrayBuffer"); } readAsDataURL(blob: Blob) { return this.readAs(blob, "readAsDataURL"); } readAsText(blob: Blob) { return this.readAs(blob, "readAsText"); } }
使用方法:
(async()=>{ const buffer1 = await new FileReaderEx().readAsArrayBuffer(blob1); const buffer2 = await new FileReaderEx().readAsDataURL(blob2); const buffer3 = await new FileReaderEx().readAsText(blob3); })();
TypeScript基于泛型
/** * @description 同步调用包装 * @param promise 需要被调用的异步方法 */ async function asyncWrap<T = any>(promise: Promise<T>): Promise<T | null> { try { return await promise; } catch (err) { return null; } } export async function fileReaderWrap<T = any>(blob: Blob, ctx: 'readAsArrayBuffer' | 'readAsDataURL' | 'readAsText'): Promise<any> { const reader = new FileReader(); reader[ctx](blob); return new Promise((resolve, reject) => { reader.onload = () => resolve(reader.result); reader.onerror = () => reject(reader.error); }); }
使用方法:
(async()=>{ const buffer1 = await asyncWrap<ArrayBuffer>(fileReaderWrap<ArrayBuffer>(file, 'readAsArrayBuffer')); const buffer2 = await asyncWrap<ArrayBuffer>(fileReaderWrap<ArrayBuffer>(file, 'readAsDataURL')); const buffer3 = await asyncWrap<ArrayBuffer>(fileReaderWrap<ArrayBuffer>(file, 'readAsText')); })();