详解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 相关文章推荐
网站繁简切换的JS遇到页面卡死的解决方法
Mar 12 Javascript
IE8下Jquery获取select选中的值post到后台报错问题
Jul 02 Javascript
js的touch事件的实际引用
Oct 13 Javascript
Jquery实现仿腾讯微博发表广播
Nov 17 Javascript
通过实例理解javascript中没有函数重载的概念
Jun 03 Javascript
js实现显示当前状态的导航效果代码
Aug 28 Javascript
Javascript 计算字符串在localStorage中所占字节数
Oct 21 Javascript
JavaScript性能优化总结之加载与执行
Aug 11 Javascript
js Element Traversal规范中的元素遍历方法
Apr 19 Javascript
jquery引入外部CDN 加载失败则引入本地jq库
May 23 jQuery
微信小程序onLaunch异步,首页onLoad先执行?
Sep 20 Javascript
jQuery 动态粒子效果示例代码
Jul 07 jQuery
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中的字符串编码转换(自动识别原编码)
2013/07/02 PHP
php读取富文本的时p标签会出现红线是怎么回事
2014/05/13 PHP
用显卡加速,轻松把笔记本打造成取暖器的办法!
2013/04/17 Javascript
jquery淡化版banner异步图片文字效果切换图片特效
2014/04/08 Javascript
Bootstrap实现响应式导航栏效果
2015/12/28 Javascript
javascript动态获取登录时间和在线时长
2016/02/25 Javascript
JS表单验证的代码(常用)
2016/04/08 Javascript
jquery过滤特殊字符',防sql注入的实现方法
2016/08/17 Javascript
Ajax使用原生态JS验证用户名是否存在
2020/05/26 Javascript
jquery判断iPhone、Android设备类型
2016/09/14 Javascript
JavaScript实现DOM对象选择器
2016/09/24 Javascript
微信小程序 视图容器组件的详解及实例代码
2017/01/19 Javascript
Linux使用Node.js建立访问静态网页的服务实例详解
2017/03/21 Javascript
jQuery实现Select下拉列表进行状态选择功能
2017/03/30 jQuery
vue使用xe-utils函数库的具体方法
2018/03/06 Javascript
微信小程序实现简易table表格
2020/06/19 Javascript
微信小程序学习笔记之目录结构、基本配置图文详解
2019/03/28 Javascript
Python利用Beautiful Soup模块创建对象详解
2017/03/27 Python
安装python3的时候就是输入python3死活没有反应的解决方法
2018/01/24 Python
Python读取mat文件,并转为csv文件的实例
2018/07/04 Python
Django Rest framework三种分页方式详解
2019/07/26 Python
解决python中导入win32com.client出错的问题
2019/07/26 Python
python DataFrame转dict字典过程详解
2019/12/26 Python
Python新手学习标准库模块命名
2020/05/29 Python
matplotlib grid()设置网格线外观的实现
2021/02/22 Python
Canvas多边形绘制的实现方法
2019/08/05 HTML / CSS
AJAX的全称是什么
2012/11/06 面试题
QQ空间主人寄语大全
2014/04/12 职场文书
教师个人读书活动总结
2014/07/08 职场文书
施工安全汇报材料
2014/08/17 职场文书
博士生专家推荐信
2015/03/25 职场文书
比赛主持人开场白
2015/05/29 职场文书
钱学森电影观后感
2015/06/04 职场文书
Python-OpenCV教程之图像的位运算详解
2021/06/21 Python
使用canvas仿Echarts实现金字塔图的实例代码
2021/11/11 HTML / CSS
vue实现拖拽交换位置
2022/04/07 Vue.js