浏览器为咱们提供了许多有用的办法,为了应用这些办法,开发者通常须要创立对应的对象,往往使得业务代码显得简短,缺乏经验的开发者对所建对象的解决形式也显得不够“优雅”。
如果对 IIFE 返回的函数能够保留其既有作用域链这一个性善加利用,就能够将这些对象的创立过程“暗藏”起来,使得业务代码更加清晰简洁。

最近在写一个图片解决利用的时候总结了一些微不足道却也不便的办法,顺手给思否的同学们分享一下。

1. 文件转 Base64

在大规模应用 FileSystem接口之前,前端读取文件次要靠 input[type='file'] 元素。开发者通常会顺手创立一个 FileReader 实例来读取文件,用完之后随即摈弃之,不得不说真是有情。实际上这个实例是能够复用起来的:

/** * @method blob2Base64 - 将 blob 文件转为 Base64 URL * @returns {Promise<String>} * */ const blob2Base64 = (() => {    const fileReader = new FileReader();    let resolver = null, errHandler = null;    fileReader.onload = () => resolver(fileReader.result);    fileReader.onerror = err => errHandler(err);        return file => {        fileReader.readAsDataURL(file);        return new Promise((resolve, reject) => {            resolver = resolve;            errHandler = reject;        })    }})();

这种代码最罕用于读取用户选取的图片,应用的时候:

const readFileFromInput = async event => {    const { target: { files: [file] }} = event;    const base64 = await blob2Base64(file);    console.log('read data as base64:', base64);}document.querySelector('input[type="file"]').addEventListener('change', readFileFromInput);

2. 从URL加载图片

前端解决图片通常依赖于 canvas ,而 canvas 绘图上下文不反对间接从 URL 读取图片,所以咱们须要创立一个图片对象,并在其加载实现后再绘制到 canvas 上,鉴于 canvas 会将图片数据复制一份,这个图片对象是能够复用的:

/** * @const loadImageFromURL - 从 URL 加载图片 * */const loadImageFromURL = (() => {    const image = new Image();    image.setAttribute('crossOrigin', 'Anonymous');    let resolver = null, errHandler = null;    image.onload = () => {        resolver(image);    };    image.onerror = err => {        errHandler(err);    };    return URL => {        return new Promise((resolve, reject) => {            resolver = resolve;            errHandler = reject;            image.src = URL;        });    }})();

当然,如果是应用 Knova 这样的绘图库的话,每增加一张图片都须要创立新的 Image 对象,这段代码稍加批改就能够胜任了。

3. 获取图片BitMap数据

借助 canvas 咱们能够将浏览器反对的所有格局的图片解码失去其位图数据,不过,这个需要并不常见,除非你想亲手实现一下二维码扫描性能。这里须要复用的,是一个 canvas 元素对象及其绘图上下文:

/** * @method imageFileToImageData - 读取图片文件的为位图数据 * @param {File} blob - 须要转换的文件对象 * @return {Promise<ImageData>} */const imageFileToImageData = (() => {    const canvas = document.createElement('canvas');    canvas.setAttribute('crossOrigin', 'Anonymous');    const context = canvas.getContext('2d');    return async blob => {        const image = await loadImageFromURL(await blob2Base64(blob));        const { width, height } = image;        canvas.setAttribute('width', width);        canvas.setAttribute('height', height);        context.drawImage(image, 0, 0, width, height);        return context.getImageData(0, 0, width, height);    };})();

下面的两个办法在这里都曾经用上了,能够看出几乎是简洁、不便、清晰到家了!

4. 文件下载

文件下载的原理是借助一个 a[download] 元素触发点击事件,同样地,这个元素也是能够复用的:

/** * 传入 URL 下载文件 * */const downLoadPicByURL = (() => {    const anchor = document.createElement('a');    return (URL, filename = 'download') => {        anchor.setAttribute('href', URL);        anchor.setAttribute('download', filename);        anchor.click();    }})();

当然,因为下载的过程没法监听更没法管制,这个办法不返回任何无效信息。