详解ES6 Promise的生命周期和创建


Posted in Javascript onAugust 18, 2019

一:Promise的概念

Promise的中文意思是‘承诺',什么叫承诺?承诺就是现在没有发生,在将来的某个时刻一定会发生的事情。
放在编程语言的环境下,Promise就是异步事件的结果的占位符。我们不用去管异步事件的结果什么时候来,只需要关心异步事件的结果产生的时候,你想要做什么就对了。

二:Promise的生命周期

异步事件不是立即执行程序,它的结果可能要在动作发生后一段时间才到,所以它有个生命周期。例如用电饭锅煮米饭,从【米下锅开始定时】到【定时结束】,这是煮米饭的生命周期。
一个Promise的生命周期主要有2个阶段:

1: unsettled(pending) 处理过程中 -> 米饭定时开始到定时结束这段期间
2: settled (fulfilled或者rejected) 处理完 -> 米饭定时结束状态

我们看到settled阶段会出现两个可能的状态fulfilled或者rejected,它们分别是什么意思呢:

1: fulfilled Promise操作完成的结果为成功 -> 煮米饭水的比例合适,饭熟了,成功
2: rejected Promise操作完成的结果为失败 -> 煮米饭水放少了,饭是夹生的,失败

Promise内部的属性PromiseState被用来表示Promise的3种状态:pending,fulfilled 和 rejected。但是我们无法读取到这三个状态,而是通过Promise提供的接口方法来书写对应的处理程序,后面会讲到。

三:如何让创建一个Promise

相信前面通过对比煮饭这个过程,你已经对Promise的概念和生命周期有了一定的体会,接下来我们就看看如何真正第创建一个Promise(如何煮米饭)。

声明:因为Promise有未完成的Promise和已完成的Promise不同类型,本篇我们只讨论未完成的Promise。已完成的Promise后面会讲,目前来说你不必关心,就当世界上没有这个东西。

通过Promise构造函数,可以创建一个Promise。构造函数只有一个参数:一个函数,我们叫它执行器(executor)函数。你可以理解为煮饭用的电饭煲。

既然执行器(executor)函数也是一个函数,那它也有参数。对,它有2个参数:

1: resolve() 执行器(executor)函数成功时的处理函数
2: reject() 执行器(executor)函数失败时的处理函数

我们用一段代码来解释一下:

let executor = function (resolve, reject) {};
let promise = new Promise(executor);

通过上面的代码示例,应该就能很清楚创建一个Promise的语法解构是怎样的了。接下来我们用一个在Node.js中读取文件的例子来演示:

let executor = function (resolve, reject) {
  let fs = require('fs');
  fs.readFile('data.txt', {encoding: 'utf8'}, function (error, content) {
    if (error) {
      reject(error); //在异步行为失败时,调用reject()方法
      return;
    }
    resolve(content); //在异步行为成功时,调用resolve()方法

  });
};
let promise = new Promise(executor);

解释一下上面的代码:

1: 创建Promise,包裹异步程序

Promise本身并不执行任何真正的异步程序。我们只是把异步程序包裹在一个Promise里面,这样做的目的其实是想把异步处理程序的结果给Promise,稍后再利用Promise提供的接口函数(then()或者catch())来对结果进行处理。

2: 我们在Promise的executor函数里调用真正的异步操作函数。

我们在executor函数里调用fs.readFile( )函数。fs.readFile( )函数本身是一个异步行为,其方法的第三个参数为一个回调函数,用来接收文件读取的结果(失败时候的error和成功时候的content)。

3: 把异步程序的结果给Promise

我们在fs.readFile( )的回调函数里,在文件读取成功时调用resolve( )方法,失败的时候调用reject( )方法,把成功或者失败的结果通过2个函数的参数传入,为Promise在fulfilled或者rejected两种状态时提供数据。

四:编写Promise结果处理程序

前面我们已经了解到了怎么把一个异步处理事件包裹在一个Promise里面,并且通过resolve()和reject()把异步处理事件的结果传递的过程。终于来到了最后一步:使用结果数据(对比现实生活,你也可以理解为这一步叫做:验证承诺)。
Promise提供2个方法来处理结果: Promise.prototype.then() 和 Promise.prototype.catch()。我们分别来看一下二者的功能:

1:Promise.prototype.then()

then()方法接收2个函数类行的参数:

1: 第一个参数为Promise在fulfilled状态(成功状态)时的回调方法
2: 第一个参数为Promise在rejected状态(失败状态)时的回调方法
我们以之前的读取文件为例子,看一下then()方法的使用:

let executor = function (resolve, reject) {
  let fs = require('fs');
  fs.readFile('data.txt', {encoding: 'utf8'}, function (error, content) {
    if (error) {
      reject(error); //在异步行为成功时,调用reject()方法
      return;
    }
    resolve(content); //在异步行为失败时,调用resolve()方法

  });
};
let promise = new Promise(executor);

//处理成功和失败的情况
promise.then(function (content) {
  console.log(content);

}, function (error) {
  console.log(error)
});

这两个回调函数的参数也就是之前异步处理的结果数据。第一个函数的参数对应resolve()的参数content,第二个回调函数对应reject()的参数error。这样我们也就能在这2个回调函数里面拿到数据,从而根据你的业务需求编写对应的结果处理程序。

需要说明的是,这两个回调函数参数都不是必须的,并不强制要求你都要处理。下面的代码里,列觉了某2种结果处理程序,语法上都是合法的。只是正常的需求下,我们一般还是需要对成功和失败都要处理。

//只处理成功的情况
promise.then(function (content) {
  console.log(content);

});
//只处理失败的情况
promise.then(null, function (error) {
  console.log(error)
});

2: Promise.prototype.catch()

catch()方法只有一个参数:一个只处理rejected状态的回调函数。可能会有人疑问,then()已经可以同时处理2个状态,为什么还需要catch()方法?

原因在于前面我们提到的,在then()方法里,并不强制要求你提供处理rejected的回调函数。Promise有个特性:如果你没有添加rejected处理函数,那所有的失败会被自动忽略。

可能会有些开发者只关心成功状态,而忘了提供rejected处理函数,从而给整个程序埋下隐患,这样会造成很不好的用户体验。而catch()方法就是一个明确地处理rejected的方法,而不像在then()里面,因为是非必须参数而让人很容易忽略。

背景说了那么多,我们看看catch()怎么用:

promise.catch(function (error) {
  console.log(error)
})

其实用法很简单,它其实等价于是有reject处理函数的then():

promise.then(null, function (error) {
  console.log(error)
});

没有语法要求一个完整的Promise处理程序必须要有catch()方法。如果你没有使用catch()的习惯,最好总是不要忘记在使用then()的时候添加reject处理函数。

或者,如果你偶尔会忘记在then()里添加reject处理函数,那么记得使用catch()来为你做最安全的保障。

以上,就是关于Promise的基本概念和使用。在平常的开发中,Promise的使用还是非常频繁的,也很好用,所以我认为掌握Promise是一个必须的功课。希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
提升你网站水平的jQuery插件集合推荐
Apr 19 Javascript
JS Map 和 List 的简单实现代码
Jul 08 Javascript
JavaScript设计模式之工厂方法模式介绍
Dec 28 Javascript
JQuery鼠标移到小图显示大图效果的方法
Jun 10 Javascript
js实现跨域的4种实用方法原理分析
Oct 29 Javascript
easyui datagrid 大数据加载效率慢,优化解决方法(推荐)
Nov 09 Javascript
如何快速上手Vuex
Feb 14 Javascript
webpack教程之webpack.config.js配置文件
Jul 05 Javascript
node基于puppeteer模拟登录抓取页面的实现
May 09 Javascript
使用jQuery动态设置单选框的选中效果
Dec 06 jQuery
vue项目中在外部js文件中直接调用vue实例的方法比如说this
Apr 28 Javascript
Antd表格滚动 宽度自适应 不换行的实例
Oct 27 Javascript
vue-cli3配置与跨域处理方法
Aug 17 #Javascript
vue中获取滚动table的可视页面宽度调整表头与列对齐(每列宽度不都相同)
Aug 17 #Javascript
vue 使用element-ui中的Notification自定义按钮并实现关闭功能及如何处理多个通知
Aug 17 #Javascript
微信小程序开发之map地图组件定位并手动修改位置偏差
Aug 17 #Javascript
微信小程序移动拖拽视图-movable-view实例详解
Aug 17 #Javascript
微信小程序框架的页面布局代码
Aug 17 #Javascript
vue实现滑动到底部加载更多效果
Oct 27 #Javascript
You might like
php记录搜索引擎爬行记录的实现代码
2018/03/02 PHP
Aster vs Newbee BO5 第一场2.19
2021/03/10 DOTA
Ext 表单布局实例代码
2009/04/30 Javascript
js判断输入是否为数字的具体实例
2013/08/03 Javascript
JS实现状态栏跑马灯文字效果代码
2015/10/24 Javascript
Angular2学习笔记——详解NgModule模块
2016/12/02 Javascript
vue组件间通信解析
2017/03/01 Javascript
最全的JavaScript开发工具列表 总有一款适合你
2017/06/29 Javascript
关于Vue实现组件信息的缓存问题
2017/08/23 Javascript
浅谈如何使用 webpack 优化资源
2017/10/20 Javascript
微信小程序 数据缓存实现方法详解
2019/08/26 Javascript
vue配置nprogress实现页面顶部进度条
2019/09/21 Javascript
vue子传父关于.sync与$emit的实现
2019/11/05 Javascript
Vue data的数据响应式到底是如何实现的
2020/02/11 Javascript
vue npm install 安装某个指定的版本操作
2020/08/11 Javascript
基于python的Paxos算法实现
2019/07/03 Python
Python 保持登录状态进行接口测试的方法示例
2019/08/06 Python
python 实现从高分辨图像上抠取图像块
2020/01/02 Python
下载与当前Chrome对应的chromedriver.exe(用于python+selenium)
2020/01/14 Python
Python更改pip镜像源的方法示例
2020/12/01 Python
BeautifulSoup中find和find_all的使用详解
2020/12/07 Python
德国百年厨具品牌WMF美国站:WMF美国
2016/09/12 全球购物
美国时尚女装在线:Missguided
2016/12/03 全球购物
英国在线滑雪板和冲浪商店:The Board Basement
2020/01/11 全球购物
电子商务专业个人的自我评价
2013/11/19 职场文书
大学生入党思想汇报
2014/01/14 职场文书
优秀通讯员事迹材料
2014/01/28 职场文书
老同学聚会感言
2014/02/23 职场文书
《彭德怀和他的大黑骡子》教学反思
2014/04/12 职场文书
《沙漠中的绿洲》教学反思
2014/04/24 职场文书
单位租房协议书样本
2014/10/30 职场文书
蓬莱阁导游词
2015/02/04 职场文书
2016教师读书思廉心得体会
2016/01/23 职场文书
2019年教师入党申请书
2019/06/27 职场文书
2019生态环境保护倡议书!
2019/07/03 职场文书
MySQL系列之五 视图、存储函数、存储过程、触发器
2021/07/02 MySQL