javascript下使用Promise封装FileReader


Posted in Javascript onFebruary 19, 2016

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 方法,还有几个事件钩子,其中 onerror 和 onload 很明显可以作为判断任务是否完成的依据。加载成功的话,就需要用到文件内容,所以将文件或文件内容传递到下一步也十分必要。

最后完成的代码如下:

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 方法。

使用刚才封装好的函数
接下来就可以在项目中使用了:

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

以上就是本文的全部内容,希望对大家的学习有所帮助。

Javascript 相关文章推荐
Javascript 按位与运算符 (&)使用介绍
Feb 04 Javascript
jquery实现可关闭的倒计时广告特效代码
Sep 02 Javascript
jQuery实现带延迟效果的滑动菜单代码
Sep 02 Javascript
javascript实现获取浏览器版本、浏览器类型
Dec 02 Javascript
jQuery实现获取绑定自定义事件元素的方法
Dec 02 Javascript
原生js实现放大镜效果
Jan 11 Javascript
JS仿淘宝搜索框用户输入事件的实现
Jun 19 Javascript
详解vue mixins和extends的巧妙用法
Dec 20 Javascript
vue.js整合mint-ui里的轮播图实例代码
Dec 27 Javascript
vue2.0 elementUI制作面包屑导航栏
Feb 22 Javascript
从0到1搭建element后台框架优化篇(打包优化)
May 12 Javascript
token 机制和实现方式
Dec 15 Javascript
javascript每日必学之循环
Feb 19 #Javascript
jQuery实现简单的DIV拖动效果
Feb 19 #Javascript
JavaScript深度复制(deep clone)的实现方法
Feb 19 #Javascript
百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换
Feb 19 #Javascript
基于JavaScript实现弹出框效果
Feb 19 #Javascript
jQuery on()绑定动态元素出现的问题小结
Feb 19 #Javascript
学习javascript文件加载优化
Feb 19 #Javascript
You might like
PHP 缓存实现代码及详细注释
2010/05/16 PHP
php站内搜索并高亮显示关键字的实现代码
2011/12/29 PHP
php+ajax实现图片文件上传功能实例
2014/06/17 PHP
php获得刚插入数据的id 的几种方法总结
2018/05/31 PHP
Codeigniter里的无刷新上传的实现代码
2019/04/14 PHP
PHPStorm 2020.1 调试 Nodejs的多种方法详解
2020/09/17 NodeJs
JavaScript 面向对象的 私有成员和公开成员
2010/05/13 Javascript
IE6下出现JavaScript未结束的字符串常量错误的解决方法
2010/11/21 Javascript
百度地图api应用标注地理位置信息(js版)
2013/02/01 Javascript
网页右键ie不支持event.preventDefault和event.returnValue (需要加window)
2013/02/22 Javascript
js 表单提交后按钮变灰的实例代码
2013/08/16 Javascript
jquery Tab效果和动态加载的简单实例
2013/12/11 Javascript
javacript使用break内层跳出外层循环分析
2015/01/12 Javascript
JS实现拖拽的方法分析
2016/12/20 Javascript
基于匀速运动的实例讲解(侧边栏,淡入淡出)
2017/10/17 Javascript
微信小程序实现顶部下拉菜单栏
2018/11/04 Javascript
JS实现的点击按钮图片上下滚动效果示例
2019/01/28 Javascript
ES6 Promise对象的应用实例分析
2019/06/27 Javascript
解决vue 子组件修改父组件传来的props值报错问题
2019/11/09 Javascript
Vue 实现v-for循环的时候更改 class的样式名称
2020/07/17 Javascript
在Django的模型中添加自定义方法的示例
2015/07/21 Python
Python生成任意范围任意精度的随机数方法
2018/04/09 Python
对Django url的几种使用方式详解
2019/08/06 Python
python实现Pyecharts实现动态地图(Map、Geo)
2020/03/25 Python
基于Python的OCR实现示例
2020/04/03 Python
HTML5样式控制示例代码
2013/11/27 HTML / CSS
深入理解HTML的FormData对象
2016/05/17 HTML / CSS
高品质和独特的产品世界:Creations and Collections
2018/01/07 全球购物
数据库面试要点基本概念
2013/10/31 面试题
在c#中using和new这两个关键字有什么意义
2013/05/19 面试题
白酒市场开发计划书
2014/01/09 职场文书
初中班级口号
2014/06/09 职场文书
明星邀请函
2015/02/02 职场文书
2016年员工年度考核评语
2015/12/02 职场文书
GoLang中生成UUID唯一标识的实现
2021/05/08 Golang
Redis监控工具RedisInsight安装与使用
2022/03/21 Redis