详解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获取客户端外网ip的简单实例
Nov 21 Javascript
用javascript关闭本窗口不弹出询问框的方法
Sep 12 Javascript
JQuery.get提交页面不跳转的解决方法
Jan 13 Javascript
Javascript常用小技巧汇总
Jun 24 Javascript
javascript实现仿百度图片的瀑布流加载效果
Apr 20 Javascript
Webpack打包慢问题的完美解决方法
Mar 16 Javascript
javascript实现table单元格点击展开隐藏效果(实例代码)
Apr 10 Javascript
JS返回顶部实例代码
Aug 09 Javascript
JS实现网页抢购功能(触发,终止脚本)
Nov 27 Javascript
解决微信浏览器缓存站点入口文件(IIS部署Vue项目)
Jun 17 Javascript
uploadify插件实现多个图片上传并预览
Sep 30 Javascript
jQuery实现的图片点击放大缩小功能案例
Jan 02 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/23 PHP
codeigniter自带数据库类使用方法说明
2014/03/25 PHP
windows8.1下Apache+Php+MySQL配置步骤
2015/10/30 PHP
用Javascript 和 CSS 实现脚注(Footnote)效果
2009/09/09 Javascript
input 输入框内的输入事件详细分析
2010/03/17 Javascript
JQuery Tips相关(1)----关于$.Ready()
2014/08/14 Javascript
javascript实现修改微信分享的标题内容等
2014/12/11 Javascript
javascript使用prototype完成单继承
2014/12/24 Javascript
微信JSSDK上传图片
2015/08/23 Javascript
解决node.js安装包失败的几种方法
2016/09/02 Javascript
Node.js的基本知识简单汇总
2016/09/19 Javascript
jQuery纵向导航菜单效果实现方法
2016/12/19 Javascript
js中小数向上取整数,向下取整数,四舍五入取整数的实现(必看篇)
2017/02/13 Javascript
js鼠标移动时禁止选中文字
2017/02/19 Javascript
基于JS对象创建常用方式及原理分析
2017/06/28 Javascript
ES6新增数据结构WeakSet的用法详解
2017/08/07 Javascript
AngularJS select加载数据选中默认值的方法
2018/02/28 Javascript
JavaScript数据结构与算法之检索算法实例分析【顺序查找、最大最小值、自组织查询】
2019/02/22 Javascript
通过JavaScript下载文件到本地的方法(单文件)
2019/03/17 Javascript
如何使用three.js 制作一个三维的推箱子游戏
2020/07/29 Javascript
原生js实现移动小球(碰撞检测)
2020/12/17 Javascript
使用python检测手机QQ在线状态的脚本代码
2013/02/10 Python
Python中用函数作为返回值和实现闭包的教程
2015/04/27 Python
初步剖析C语言编程中的结构体
2016/01/16 Python
PyQt4 treewidget 选择改变颜色,并设置可编辑的方法
2019/06/17 Python
python实现批量修改服务器密码的方法
2019/08/13 Python
Python 面向对象之类class和对象基本用法示例
2020/02/02 Python
Python OpenCV去除字母后面的杂线操作
2020/07/05 Python
4款Python 类型检查工具,你选择哪个呢?
2020/10/30 Python
黄色火烈鸟:De Gele Flamingo
2019/03/18 全球购物
预备党员入党思想汇报
2014/01/04 职场文书
说明书怎么写
2014/05/06 职场文书
教师一帮一活动总结
2014/07/08 职场文书
实习协议书范本
2014/09/25 职场文书
八项规定整改方案
2014/10/01 职场文书
企业党员岗位承诺书
2015/04/27 职场文书