Javascript和Typescript下如何通过 async/await 优雅地使用 FileReader

Javascript和Typescript下如何通过 async/await 优雅地使用 FileReader

FileReader的使用机会很多,但是它是异步的,因此很容易出现回调地狱。

我们可以使用async/await特性,它允许我们以同步的方式调用异步代码。

封装成方法

javascript 复制代码
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);
    });
}

使用方法:

typescript 复制代码
(async()=> {
    const buffer1 = await readTextFile(file);
    const buffer2 = await readBinaryFile(file);
    const buffer3 = await readAsText(file);
})();

Javascript封装成一个class

javascript 复制代码
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");
    }
}

使用方法:

javascript 复制代码
(async()=>{
    const buffer1 = await new FileReaderEx().readAsArrayBuffer(blob1);
    const buffer2 = await new FileReaderEx().readAsDataURL(blob2);
    const buffer3 = await new FileReaderEx().readAsText(blob3);
})();

TypeScript封装成一个class

typescript 复制代码
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");
    }
}

使用方法:

javascript 复制代码
(async()=>{
    const buffer1 = await new FileReaderEx().readAsArrayBuffer(blob1);
    const buffer2 = await new FileReaderEx().readAsDataURL(blob2);
    const buffer3 = await new FileReaderEx().readAsText(blob3);
})();

TypeScript基于泛型

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);
    });
}

使用方法:

typescript 复制代码
(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'));
})();

参考资料

相关推荐
ttod_qzstudio1 分钟前
TypeScript 配置全解析:tsconfig.json、tsconfig.app.json 与 tsconfig.node.json 的深度指南
typescript·node.js·json
liliangcsdn5 分钟前
mac mlx大模型框架的安装和使用
java·前端·人工智能·python·macos
CssHero9 分钟前
基于vue3完成领域模型架构建设
前端
PanZonghui12 分钟前
用项目说话:我的React博客构建成果与经验复盘
前端·react.js·typescript
挽淚14 分钟前
JavaScript 数组详解:从入门到精通
javascript
言兴15 分钟前
教你如何理解useContext加上useReducer
前端·javascript·面试
FanetheDivine18 分钟前
过于ts的ts不是好ts
typescript
sunbyte18 分钟前
50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | GoodCheapFast(Good - Cheap - Fast三选二开关)
前端·javascript·css·vue.js·tailwindcss
前端的日常20 分钟前
网页视频录制新技巧,代码实现超简单!
前端
前端的日常21 分钟前
什么是 TypeScript 中的泛型?请给出一个使用泛型的示例。
前端