Promise初步详解(resolve,reject,catch)

一:何为Promise?

为了直观一点,首先我们采用console.dir(Promise)看一下它的结构组成。

从上面的图片中我们可以到,Promise其实是一个构造函数,它有resolve,reject,race等静态方法;它的原型(prototype)上有then,catch方法,因此只要作为Promise的实例,都可以共享并调用Promise.prototype上面的方法(then,catch),接下来我们试着使用一下Promise。

二:Promise的使用


首先我们来看一下Promise的使用语法:

new Promise(function(resolve,reject){}/*excutor*/);

在实例化Promise时需要传入一个函数excutor作为参数,并且在Promise构造函数执行时同步执行。废话不多说,先看一个简单的实例:

   var p = new Promise(function(resolve,reject){var timer = setTimeout(function(){console.log('执行操作1');},1000);});

我们可以看到1s后在控制台输出相应的结果,这就说明在实例化过程中,作为参数的excutor函数也会执行。

从上面的实例中我们看到,excutor函数还有两个参数resolve和reject,其实这两个参数也是函数,在excutor执行时被调用,下面我们具体来谈谈resolve和reject的用法。

三:resolve和reject的具体用法

1.先来说说resolve的用法

首先我们来看看Promise的几种状态:

pending: 初始状态,成功或失败状态。

fulfilled: 意味着操作成功完成。

rejected: 意味着操作失败。

当我们在excutor函数中调用resolve方法时,Promise的状态就变成fulfilled,即操作成功状态,还记得上面Promise.prototype上面的then和catch方法吗?当Promise状态为fullfilled状态时执行then方法里的操作,注意了,then方法里面有两个参数onfulfilled(Promise为fulfilled状态时执行) 和onrejected(Promise为rejected状态时执行),步骤如下:

1.实例化Promise(new Promise(function(resolve,reject)))

2.用Promise的实例调用then方法。

具体来看下面的例子:

    var p = new Promise(function (resolve, reject) {var timer = setTimeout(function () {console.log('执行操作1');resolve('这是数据1');}, 1000);});p.then(function (data) {console.log(data);console.log('这是成功操作');});

简单的理解就是调用resolve方法,Promise变为操作成功状态(fulfilled),执行then方法里面onfulfilled里的操作。其实then里面的函数就是我们平时所说的回调函数,只不过在这里只是把它分离出来而已。我们可以看到控制台上的输出结果如下所示:

2.reject的用法

看了上面的实例,我相信应该也很容易理解reject方法了,就是调用reject方法后,Promise状态变为rejected,即操作失败状态,此时执行then方法里面onrejected操作,上面我们提到了then方法有两个参数,一种是Promise状态为fulfilled时执行(onfullfilled),一种是Promise状态为rejected时执行(onrejected),其实就是类似于jquery里的hover方法里面的两个参数一样,来看看下面的例子:

    var p = new Promise(function (resolve, reject) {var flag = false;if(flag){resolve('这是数据2');}else{reject('这是数据2');}});p.then(function(data){//状态为fulfilled时执行console.log(data);console.log('这是成功操作');},function(reason){ //状态为rejected时执行console.log(reason);console.log('这是失败的操作');});

 我们可以看到输出结果:

三:catch方法

我们注意到除了then方法外,Promise原型上还有另外一个叫catch的方法,那么这个方法的作用是什么呢?其实跟then方法中的第二个参数一样,就是在Promise状态为rejected时执行,then方法捕捉到Promise的状态为rejected,就执行catch方法里面的操作,下面用catch方法改写上面reject用法里面的例子,如下所示:

  var p = new Promise(function (resolve, reject) {var flag = false;if(flag){resolve('这是数据2');}else{reject('这是数据2');}});p.then(function(data){console.log(data);console.log('这是成功操作');}).catch(function(reason){console.log(reason);console.log('这是失败的操作');});

执行结果和上面reject用法的例子一样。

四.为何用Promise

首先我们来看这样一个例子,取4个定时器,设置延迟时间都为1s,然后每隔1s依次在控制台输出‘我’‘爱’‘米’‘饭’的字样。代码如下:

      setTimeout(function () {console.log('我');setTimeout(function () {console.log('爱');setTimeout(function () {console.log('米');setTimeout(function () {console.log('饭');}, 1000);}, 1000);}, 1000);}, 1000);

发现什么问题没有?是不是有点感觉回调函数的嵌套有点多,如果有更多的回调函数呢?是不是使代码的可读性和可维护性都大大降低了呢(回调地狱?),这时如果我们使用Promise去实现这个效果,虽然可能代码不会减少,甚至更多,但是却大大增强了其可读性和可维护性。具体看下面例子:

            function getStr1() {return new Promise(function (resolve, reject) {setTimeout(function () {resolve('我');}, 1000);});}function getStr2() {return new Promise(function (resolve, reject) {setTimeout(function () {resolve('爱');}, 1000);});}function getStr3() {return new Promise(function (resolve, reject) {setTimeout(function () {resolve('米');}, 1000);});}function getStr4() {return new Promise(function (resolve, reject) {setTimeout(function () {resolve('饭');}, 1000);});}getStr1().then(function (data) {console.log(data);return getStr2();}).then(function (data) {console.log(data);return getStr3();}).then(function (data) {console.log(data);return getStr4();}).then(function (data) {console.log(data);})

执行效果跟上面一样,在这个例子中,将得到Promise实例的过程封装成一个函数(getStr1,getStr2,getStr3,getStr4)并返回一个Promise实例,再用实例去调用相应的then方法,在每个then方法中通过return得到下一级的Promise实例,比如在第一个Promise实例(getStr1())then方法中,通过return返回下一个Promise对象(getStr2()),然后再去调用then方法执行里面的操作,再返回下一个Promise对象(这里是getStr3()),这样一级一级下去实现了链式调用,虽然代码量增加了,但比起前面的层层嵌套,显然这种方式使得代码更易读更易维护。

本文对Promise的介绍就到这里,欢迎大家指正里面的错误和不准确的地方。

转载于:https://www.cnblogs.com/homeStrong/p/8231889.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/414954.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Fragment生命周期与宿主Activity生命周期

当启动activity是,同时启动activity里面的fragment,各生命周期的起调流程 11-22 16:51:22.051 8358-8358/com.txjifei.mapclient.liteapp E/lgqq: ...ActivityonCreate11111 11-22 16:51:22.070 8358-8358/com.txjifei.mapclient.liteapp E/lgqq: ...Ac…

docker安装mongodb

1、拉取镜像 docker pull mongo:latest2、创建容器 docker create --name mongodb --restartalways -p 27017:27017 -v mongodb:/data/db mongo:latest3、启动容器 docker start mongodb4、进入容器 docker exec -it mongodb /bin/bash5、输入命令行mongo,进入m…

session 的 源码

session 的 源码 1.session 和 cookie 的 区别: 答: cookie 它是保存在浏览器的键值对。 session 它是保存在服务端的键值对。 它 依赖cookie 存在。 流程: 一个服务端, 一个客户端第一次来 服务端 去 客户端 发来的请求里的…

前端学习(2682):重读vue电商网站3之登录页面总结el-form 组件问题

el-form 组件默认是 content-box,我们设置其如下属性时,就会出现长度比我们想象中长一点的情况。 .login_form {position: absolute;bottom: 60px;width: 100%;padding: 0 20px; //多加一行box-sizing: border-box; } 运行结果

js处理富文本编辑器转义、去除转义、去除HTML标签

富文本编辑器生成的HTML标签&#xff0c;进行转义&#xff0c;然后写入数据库&#xff0c;防止脚本注入&#xff1a; function htmlEncode(value){return $(<div/>).text(value).html(); }从数据库拿出的转义后的HTML标签内容&#xff0c;先得去除转义&#xff0c;然后再…

Android 统一View样式,textview样式

xmlns:tools"http://schemas.android.com/tools" android:text"提示" 1、在values文件夹下的styles文件里面创建textview样式——android:style/Widget.TextView可以替换为其他view,如&#xff1a;button,CheckBox。。。。。 <style name"mytextst…

前端学习(2683):重读vue电商网站4之登录页面总结使用 iconfont 给输入框添加图标

在 main.js 中导入字体图标 然后在 el-input 组件中通过 prefix-icon 进行相关图标引用 最终效果图如下&#xff1a;

hadoop之文件管理基本操作

# 格式化hdfs hadoop namenode -format # 查看hadoop下的文件夹 hadoop fs -ls # 创建hdfs文件夹 hadoop fs -mkdir /user/input # 将本地文件file.txt 复制到新建文件夹,file->hdfs hadoop fs -put /user/wangbin/input/ip_data.txt wangbin # 从hadoop复制到hadoop # 从wa…

Highcharts隐藏网格线

原始效果 加上代码 yAxis: {gridLineWidth: 0,minorGridLineWidth: 0}

前端学习(2684):重读vue电商网站5之登录页面总结如何进行表单验证

Form 组件提供了表单验证的功能&#xff0c;只需要通过 rules 属性传入约定的验证规则&#xff0c;并将 Form-Item 的 prop 属性设置为需校验的字段名即可。 通过 rules 属性传入约定的验证规则 将Form-Item 的 prop 属性设置为需校验的字段名

Android 贴纸样式标签

demo链接&#xff1a;https://download.csdn.net/download/meixi_android/10802704 样式效果 实现方法&#xff1a; 1、自定义标签类 public class LabelImageView extends ImageView {LabelViewHelper utils;public LabelImageView(Context context) {this(context, null);…

Java研发工程师面试题(1)

Java研发工程师面试题(1) 基础题 一、String,StringBuffer, StringBuilder 的区别是什么&#xff1f;String为什么是不可变的&#xff1f;1. String是字符串常量&#xff0c;StringBuffer和StringBuilder是字符串变量。StringBuffer是线程安全的&#xff0c;StringBuilder是非线…

javascript 树结构过滤保留原始结构

需求&#xff1a;有一个树结构的JSON&#xff0c;被过滤后&#xff0c;希望结构保留树结构。 var tree [{text: "Parent 1",nodes: [{text: "Child 1",type: "Child",nodes: [{text: "Grandchild 1"type: "Grandchild"},{…

前端学习(2685):重读vue电商网站6之如何重置表单

element-ui 对表单提供了如下方法 resetFields&#xff0c;我们只需要获取表单对象数据即可重置我们的表单。 获取表单对象方式如下&#xff1a; 直接在表单处添加 ref属性&#xff0c;如下 loginFormRef&#xff0c;此引用即为我们表单实例。 然后&#xff0c;在我们重置按钮…

android Camera 设置焦距

1、添加Camera权限 2、判断是否支持变焦 public boolean isSupportZoom(){boolean isSuppport true;if (mCamera.getParameters().isSmoothZoomSupported()){isSuppport false;}return isSuppport;} 3、修改焦距 public void setZoom(){if (mIsSupportZoom){try{Parameters …

v-contextmenu的使用(右键菜单)

先来个自己改写的图&#xff1a; 代码&#xff1a; 结构&#xff1a;<div class"wrap" v-contextmenu:contextmenu><v-contextmenu ref"contextmenu"> <v-contextmenu-item ><i class"fa fa-search"></i>上插入&l…

js 树形json转以叶子结点为基准的扁平结构

需求&#xff0c;我需要根据树形结构&#xff0c;来实现自定义表格&#xff0c;所以需要转化&#xff0c;下面是代码&#xff1a; const shortid require(shortid)const data [{name: a,children: [{name: b,children: [{ name: e }, { name: i }],},{ name: c, children: […

前端学习(2686):重读vue电商网站7之登录预校验

在我们点击登录按钮&#xff0c;不应该直接发起网络请求&#xff0c;而是应该对表单进行预校验&#xff0c;检验成功才会发送请求。 拿到表单引用对象&#xff0c;即可进行对表单的校验。 首先&#xff0c;给登录按钮通过 click 来绑定一个事件 下一步&#xff0c;在 methods …

Android 循环滚动控件ViewFlipper,可实现跑马灯或轮播图效果

ViewFlipper——Android循环滚动控件 1、效果如下&#xff1a; 2、实现方法 &#xff08;1&#xff09;创建进出动画 上下滚动动画 y_in.xml <?xml version"1.0" encoding"utf-8"?> <set xmlns:android"http://schemas.android.com/a…