详解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:ajax实现翻页无刷新功能代码
Aug 05 Javascript
jquery实现的一个文章自定义分段显示功能
May 23 Javascript
javascript中定义类的方法汇总
Dec 28 Javascript
js支持键盘控制的左右切换立体式图片轮播效果代码分享
Aug 26 Javascript
jquery ajax双击div可直接修改div中的内容
Mar 04 Javascript
js停止冒泡和阻止浏览器默认行为的简单方法
May 15 Javascript
Angular 路由route实例代码
Jul 12 Javascript
jQuery webuploader分片上传大文件
Nov 07 Javascript
React学习笔记之条件渲染(一)
Jul 02 Javascript
js中自定义react数据验证组件实例详解
Oct 19 Javascript
jquery实现选项卡切换代码实例
May 14 jQuery
JavaScript仿京东轮播图效果
Feb 25 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 面向对象实现代码
2009/11/11 PHP
php自动获取字符串编码函数mb_detect_encoding
2011/05/31 PHP
thinkphp 一个页面使用2次分页的实现方法
2013/07/15 PHP
分享PHP header函数使用教程
2013/09/05 PHP
getimagesize获取图片尺寸实例
2014/11/15 PHP
PHP编写daemon process 实例详解
2016/11/13 PHP
使用PHP反射机制来构造"CREATE TABLE"的sql语句
2019/03/21 PHP
PHP实现文件上传后台处理脚本
2020/03/04 PHP
从JavaScript 到 JQuery (1)学习小结
2009/02/12 Javascript
javascript 当前日期加(天、周、月、年)
2009/08/09 Javascript
javascript获取选中的文本的方法代码
2013/10/30 Javascript
同域jQuery(跨)iframe操作DOM(实例讲解)
2013/12/19 Javascript
在javascript中执行任意html代码的方法示例解读
2013/12/25 Javascript
jQuery之Deferred对象详解
2014/09/04 Javascript
jQuery实现图片走马灯效果的原理分析
2016/01/16 Javascript
Js得到radiobuttonlist选中值的两种方法(推荐)
2016/08/25 Javascript
史上最全JavaScript数组去重的十种方法(推荐)
2017/08/17 Javascript
JS+HTML实现的圆形可点击区域示例【3种方法】
2018/08/01 Javascript
对于防止按钮重复点击的尝试详解
2019/04/22 Javascript
简单通过settimeout看javascript的运行机制
2019/05/10 Javascript
Javascript模拟实现new原理解析
2020/03/03 Javascript
python定时采集摄像头图像上传ftp服务器功能实现
2013/12/23 Python
python操作redis的方法
2015/07/07 Python
Python实现MySQL操作的方法小结【安装,连接,增删改查等】
2017/07/12 Python
python GUI库图形界面开发之PyQt5打开保存对话框QFileDialog详细使用方法与实例
2020/02/27 Python
python图片合成的示例
2020/11/09 Python
HTML5之SVG 2D入门2—图形绘制(基本形状)介绍及使用
2013/01/30 HTML / CSS
DJI大疆德国官方商城:大疆无人机
2018/09/01 全球购物
瑞士图书网站:Weltbild.ch
2019/09/17 全球购物
公司新员工的演讲稿注意事项
2014/01/01 职场文书
初三学生个人自我评定
2014/04/06 职场文书
新闻学专业职业生涯规划范文:我的人生我做主
2014/09/12 职场文书
刑事辩护授权委托书格式
2014/10/13 职场文书
长江三峡导游词
2015/01/31 职场文书
美德少年事迹材料(2016推荐版)
2016/02/25 职场文书
六年级作文之关于梦
2019/10/22 职场文书