资讯专栏INFORMATION COLUMN

使用 Promise 封装 FileReader

zhongmeizhi / 1779人阅读

摘要:将其加入规范,也修改实现向规范靠拢发布公告。封装接下来开始封装。使用刚才封装好的函数接下来就可以在项目中使用了支持两个参数,第一个在成功时启动,第二个自然在失败时启动。

我近期在 SF 做了一场关于 Promise 的专题分享,做的很用心,内容也很丰富,基本可以一站式解决所有关于 Promise 的问题。欢迎大家前来围观:

Promise 的 N 种用法

Promise 在处理异步的时候是个很好的选择,可以减少嵌套层次,让代码更好读,逻辑更清晰。ES6 将其加入规范,jQuery 3.0 也修改实现向规范靠拢(3.0 发布公告)。一些新增元素比如 .fetch() 原生就 “thenable”,不过大多数以往的 API 还要依赖回调,这个时候,我们只要将它们重新封装,就能避开嵌套陷阱,享受 Promise 带来的愉悦体验。

Promise 一般用法

先来看下 Promise 的一般用法。

// 声明 Promise 对象
var p = new Promise(function (resolve, reject) {
  // 不管啥时候,该执行then了,就调用 resolve
  setTimeout(function () { 
    resolve(1);
  }, 5000);

  // 或者不管啥问题,就调用 reject
  if (somethingWrong) {
    reject("2");
  }      
});
    
// 使用 Promise 对象
p.then(function (num) {
  // 对应上面的 resolve
  console.log(num); // 1
}, function (num) {
  // 对应上面的 reject
  console.log(num); // 2
});

Promise 的驱动模型并不复杂:任何操作,假定它只有两个结果,成功或者失败。那么只需要在合适的时间调用合适的程序,进入合适的后续步骤即可。.then() 顾名思义,就是下一步的意思,当前面的 Promise 有了结果——即调用 resolve 或者 reject——之后,就启动对应的处理函数。

Promise 实例创建后就会开始执行,判定结果需要我们自己来,比如加载成功,或者满足某个条件,等等。通过串联 .then() 则可以完成一系列操作。每次调用 .then() 都会创建一个新的 Promise 实例,它会静静等待前面的实例状态改变后再开始执行。

封装 FileReader

接下来开始封装。思路很简单,FileReader 除了提供各种 read 方法,还有几个事件钩子,其中 onerroronload 很明显可以作为判断任务是否完成的依据。加载成功的话,就需要用到文件内容,所以将文件或文件内容传递到下一步也十分必要。

最后完成的代码如下:

function reader (file, options) {
  options = options || {};
  return new Promise(function (resolve, reject) {
    let reader = new FileReader();

    reader.onload = function () {
      resolve(reader);
    };
    reader.onerror = reject;

    if (options.accept && !new RegExp(options.accept).test(file.type)) {
      reject({
        code: 1,
        msg: "wrong file type"
      });
    }

    if (!file.type || /^text//i.test(file.type)) {
      reader.readAsText(file);
    } else {
      reader.readAsDataURL(file);
    }
  });
}

为了能真正派上用场,里面还有一些验证文件类型的操作,不过跟本文主旨无关,略过不表。这段代码的核心是创建一个 Promise 对象,等待 FileReader 读取完成后调用 resolve 方法,或者出现问题时调用 reject 方法。

Github Gist 里也放了一份。

使用刚才封装好的函数

接下来就可以在项目中使用了:

reader(file)
  .then(function (reader) {
    console.log(reader.result);
  })
  .catch(function (error) {
    console.log(error);
  });

.then() 支持两个参数,第一个在 Promise 成功时启动,第二个自然在失败时启动。用 .catch() 可以实现同样地效果。Promise 的好处除了可读性更佳以外,返回的 Promise 对象还可以任意传递,继续进行链式调用,有很大想象空间。

继续 .then()

于是我们不妨串联更多操作(本来想写个断点续传的,回头再说吧):

reader(file)
  .then(function (reader) {
    return new Promise(function (resolve, reject) {
      // 就随便暂停个5秒吧……
      setTimeout(function () {
        resolve(reader.result); 
      }, 5000);
    });
  })
  .then(function (content) {
    console.log(content);
  });
总结

这其实是我第一次用 Promise,上次翻译 jQuery 发布公告的时候我它也只是一知半解,对它的解读也糊里糊涂。我很喜欢在业余项目中学习使用新技术,最近开发 Chrome 插件的时候就尝试了一把,感觉不错。使用过程比我想象的复杂也比我想象的简单,这套设计很棒,能解决不少实际问题,也给了我很大启发,将来我应该会把很多地方的实现都做这样的修改。

参考文献

除去第一段的各个链接,还有一些文章值得一看。

ECMAScript 6 入门:Promise 对象

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/78676.html

相关文章

  • 你知道前端对图片的处理方式吗?

    摘要:对于第二种存储方式,我们前端需要将其二进制流交由对象处理,然后通过的生成临时赋值给属性来显示。当后端返回特定的图片二进制流的时候,就像我第一里的情景再现说的,前端用容器接收。 前言 作为前端工程师 de 我们,日常少不了会跟图片打交道。在各大电商平台工作的前端工程师们,感受可能会更加的明显。 以下是我之前跟图片打交道踩到的坑,跟大家分享一下经验。 一、情景再现 用postman请求接口...

    helloworldcoding 评论0 收藏0
  • 你知道前端对图片的处理方式吗?

    摘要:对于第二种存储方式,我们前端需要将其二进制流交由对象处理,然后通过的生成临时赋值给属性来显示。当后端返回特定的图片二进制流的时候,就像我第一里的情景再现说的,前端用容器接收。 前言 作为前端工程师 de 我们,日常少不了会跟图片打交道。在各大电商平台工作的前端工程师们,感受可能会更加的明显。 以下是我之前跟图片打交道踩到的坑,跟大家分享一下经验。 一、情景再现 用postman请求接口...

    LiuRhoRamen 评论0 收藏0
  • 你知道前端对图片的处理方式吗?

    摘要:对于第二种存储方式,我们前端需要将其二进制流交由对象处理,然后通过的生成临时赋值给属性来显示。当后端返回特定的图片二进制流的时候,就像我第一里的情景再现说的,前端用容器接收。 前言 作为前端工程师 de 我们,日常少不了会跟图片打交道。在各大电商平台工作的前端工程师们,感受可能会更加的明显。 以下是我之前跟图片打交道踩到的坑,跟大家分享一下经验。 一、情景再现 用postman请求接口...

    Zachary 评论0 收藏0
  • web worker 的传值方式以及耗时对比

    摘要:背景前一阵子开发的项目导入由于自己的代码问题引起了个性能问题一个的文件转换成数据大概要耗时虽然后面发现是某个使用频率非常高的函数内部用了构造函数造成的所以这里顺便提醒一下如果你很在乎几毫秒的差距的话建议谨慎使用哈但是在优化的过程中一度怀疑是 背景 前一阵子开发的项目 pptx 导入, 由于自己的代码问题,引起了个性能问题,一个 40p 的 pptx 文件,转换成 json 数据,大概要...

    warkiz 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<