详解 ES6中 Promise 构造函数的使用

news/2024/7/10 22:35:23 标签: es6, javascript, 前端

文章目录

  • 前言
  • 什么是 Promise?
  • Promise 的几种状态
  • 拆分细解 Promise
  • Promise all()方法
  • then()方法 返回一个新的 Promise 时的状态由什么决定?
  • 总结


前言

Promise 是ES6 新增的一个异步调用解决方案,它的出现是为了解决异步函数的 回调地狱 的问题。

在这里插入图片描述

什么是 Promise?

从语法层面 来说 Promise 是一个构造函数,从功能上来说 Promise 对象用来封装一个异步操作,并且可以获得请求的结果数据。参数接收一个 回调函数(也被叫做执行器函数用于执行异步操作),接收两个参数 resolve reject,当请求成功会自动调用 resolve失败则调用 reject。并且会将执行结果返回给 Promise 的实例对象。

一个 Promise 对象代表一个在这个 Promise 被创建出来时不一定已知值的代理。它让你能够把异步操作最终的成功返回值或者失败原因和相应的处理程序关联起来。这样使得异步方法可以像同步方法那样返回值:异步方法并不会立即返回最终的值,而是会返回一个 promise,以便在未来某个时候把值交给使用者。

同时 Promise 又有承诺的意思,意思是,约定好一件事,如果当下不能完成,后续一定会去处理完成,表示暂未完成,未来一定会完成的一种状态。


Promise 的几种状态

一个 Promise 对象拥有 三种状态,在同一时刻必然处于以下几种状态之一:

  • 待定(pending):初始状态,既没有被兑现,也没有被拒绝。
  • 已兑现(fulfilled):意味着操作成功完成。
  • 已拒绝(rejected):意味着操作失败。

1.pengding:意思是 待定的,即将要发生的, 这是 Promise 的初始化状态 ,如果创建 Promise 对象的时候,且没有调用resolve或者是reject方法 ,这时候状态就会为 pending,,这个初始化状态会随着你调用了 resolve,或者是reject函数而切换到另一种状态。

待定状态的 Promise 对象要么会通过一个值被兑现,要么会通过一个原因(错误)被拒绝。当这些情况之一发生时,我们用 Promise 的 then 方法排列起来的相关处理程序就会被调用。如果 Promise 在一个相应的处理程序被绑定时就已经被兑现或被拒绝了,那么这个处理程序也同样会被调用,因此在完成异步操作和绑定处理方法之间不存在竞态条件。

在这里插入图片描述

2.fulfilled: 表示成功了解决了,并且兑现了 “承诺”, 状态已经从 pending 转变成 fulfilled 了,要实现从 pending fulfilled 的转变,需要在创建Promise对象时,在函数体中调用了resolve方法。

在这里插入图片描述
3.rejected: 表示失败了,虽然得到了返回结果,但并不是我想要的,代码拒绝往后执行。要实现从pendingrejected的转换,只需要在创建Promise对象时,调用reject函数。

在这里插入图片描述

最后不管是成功还是失败,都会有一个结果,通常我们将成功数据称为 value,失败的数据称为 reason,并且当 Promise 的状态改变后,就不会再变了,是不可逆的。状态的改变伴随着事件的触发,一个 Promise 的状态只能被改变一次。

javascript">console.dir(Promise)

浏览器输出 Promise 原型对象,可以看见在它身上有很多属性方法。
在这里插入图片描述
Promise 的实例身上都会有 一个 then 方法,如上图,该方法有两个函数作为参数 .then(resolvedFunc, rejectedFunc)

  • resolvedFunc 状态成功时执行的回调函数
  • rejectedFunc 状态失败时执行的回调函数

所以说,如果返回的值,依然是一个 Promise ,那么就可以进行 then 方法的 链式调用


拆分细解 Promise

Promise 构造函数接收一个 callback 作为参数,这个 callback 被称为回调函数,用于执行异步操作:

javascript">let pro = new Promise(() => { })
console.log(pro);     // Promise {<pending>} 所有 Promise 初始状态都为 pending

回调函数接收两个参数 resolve, reject ,它们的类型都为 一个 function

javascript">let pro = new Promise((resolve, reject) => {
//执行异步任务请求的操作
})
console.log(pro);

异步请求如果,成功就调用 resolve,失败就调用 reject。最终的返回数据结果 ,会返回到 实例对象 pro上。

javascript">let pro = new Promise((resolve, reject) => {
//执行异步任务请求的操作
// 请求处理成功后调用 resolve(value)  把成功的数据返回出去
//请求处理如果 失败后调用 reject(reason) 把失败的信息也给返回出去

})
console.log(pro);

最后实例对象 pro 身上会有 一个 then 方法,同样可以接收两个回调函数作为参数。一旦在 Promise 函数中 成功调用了 resolve() 将会执行 then 中第一个回调函数,失败则会执行 then 的第二个回调函数:

javascript">pro().then(
    value => { console.log(value)},
    reason => { console.log(reason)}
)

流程图例:
在这里插入图片描述

案例

javascript">let pro = new Promise((resolve, reject) => {
    let a = 10;
    setTimeout(() => {
        if (a > 5) {
            resolve(a)
        } else {
            reject(a)
        }
    }, 5000)
})
console.log(pro);
pro.then(
    value => { console.log("成功的" + value) },
    reason => { console.log("失败的" + reason) }
)

当我们案例中 a 大于5的时候, resolve 方法调用,返回数据, 在 then 方法中第一个 value 回调参数输出成功返回的值。
在这里插入图片描述

反之,当我们案例中 a 小于5 的时候, reject 方法调用,返回数据, 在 then 方法中 第二个 reason 回调参数输出失败返回的值。
在这里插入图片描述

Promise 实例化 执行流程图例:

在这里插入图片描述
使用 catch 替代 then 的第二个回调

虽然 then 方法,可以接收两个参数,用来输出 成功 和 失败的信息,但是建议 then 方法只用来输出 成功 的信息,失败的信息可以用 catch() 来输出,这样显得更具语义化以及结构化,更加的清晰。

如:

javascript">let pro = new Promise((resolve, reject) => {
    let a = 4;
    setTimeout(() => {
        if (a > 5) {
            resolve(a)
        } else {
            reject(a)
        }
    }, 5000)
})
console.log(pro);
pro.then(value => {
    console.log("成功的" + value)
}).catch(reason => {
    console.log("失败的" + reason) 
})

需注意一点: Promise 的那个回调函数,实际上是一个 同步回调函数,只是当遇到 resolve() 或者 reject() ,时会调用 then方法,而 then ,方法是属于以前的回调,所以 then 方法中的 回调 是异步回调函数。如下案例,分析输出的顺序 。

javascript">let pm = new Promise((resolve, reject) => {
  console.log(1);
  resolve();
  console.log(2);
});
console.log(3);
pm.then(() => {
  console.log(4);
});
console.log(5);

案例印证了上面的观点。
在这里插入图片描述


Promise all()方法

all 方法用来将 多个 Promise 实例包裹成一个新的 Pomise 实例,它接收 一个数组作为参数,数组中,传入 N个 Promise 对象,返回一个新的 Promise。

javascript">let p1 = new Promise((resolve, reject) => {
  setTimeout(function () {
    resolve(1);
  }, 1000);
});
let p2 = new Promise((resolve, reject) => {
  setTimeout(function () {
    resolve(2);
  }, 5000);
});
let p3 = new Promise((resolve, reject) => {
  setTimeout(function () {
    resolve(3); 
  }, 200);
});
Promise.all([p1, p2, p3])
  .then((values) => {
    console.log(values);   //  [1, 2, 3]
  })
  .catch((reason) => {
    console.log(reason);
  }); 

上面案例中,有 3个 Promise 实例对象的回调函数,通过 all 方法,将多个 Promise 进行包裹处理,异步的执行顺序,会按照参数中,所定义的顺序来进行执行。

值得注意:只有当数组中的 Promise 全部都为成功 状态的时候,才会触发 then 方法,若其中有一个为失败的状态,则就会 直接触发 catch 方法返回失败的信息,不会触发,then 方法。

then()方法 返回一个新的 Promise 时的状态由什么决定?

返回的新的 Promise 的状态,主要是根据 前一个 Promise 对象的返回值来决定的。

大致分为以下几种状态情况。

  • 若抛出异常,新 Promise 状态变为 rejected,reason 为抛出的异常原因
  • 若返回非 Promise 的值,新 promise 状态变为 resolved,value 为返回的值
  • 若返回新的 Promise 结果就成为新 promise 的结果

总结

以上就是给大家 带来的 ES6 中 Promise 的概念用法,如今越来越多的封装框架化,确实带来了很多的便利,但是也不要忘记了掌握很多的原生的语法逻辑,有时候,回过头来,再看一看原生的东西,又是另一番感觉和领悟!


🚵‍♂️ 博主座右铭:向阳而生,我还在路上!
——————————————————————————————
🚴博主想说:将持续性为社区输出自己的资源,同时也见证自己的进步!
——————————————————————————————
🤼‍♂️ 如果都看到这了,博主希望留下你的足迹!【📂收藏!👍点赞!✍️评论!】
——————————————————————————————


http://www.niftyadmin.cn/n/248373.html

相关文章

STM32开发(十六)STM32F103 片内资源 —— 实时时钟RTC 详解

文章目录 一、基础知识点二、开发环境三、STM32CubeMX相关配置四、Vscode代码讲解五、结果演示串口显示乱码解决方案 一、基础知识点 本实验通过stm32片内资源RTC实现实时时钟&#xff0c;通过数码管显示时间。设定闹钟&#xff0c;实现准点报时。 数码管相关知识点&#xff1…

Android:usb转232串口通信

准备工作 首先得adb进入盒子root模式&#xff0c;将/dev/ttys1这个文件改为777&#xff0c;使得所有用户可操作 adb root adb remount adb shell 进入设备的root模式&#xff0c;执行 chmod 777 /dev/ttys1 执行完成后退出 exit 再执行 adb shell chmod 666 /dev/ttyS1 如…

今天面了个字阿里拿38K出来的,真是纹身师闭眼,秀了我一脸啊

公司前段缺人&#xff0c;也面了不少测试&#xff0c;前面一开始瞄准的就是中级的水准&#xff0c;也没指望来大牛&#xff0c;提供的薪资在15-20k&#xff0c;面试的人很多&#xff0c;但平均水平很让人失望。看简历很多都是4年工作经验&#xff0c;但面试中&#xff0c;不提测…

Unity-ML-Agents-代码解读-RollerBall

使用版本&#xff1a;https://github.com/Unity-Technologies/ml-agents/releases/tag/release_19 文件路径&#xff1a;ml-agents-release_19/docs/Learning-Environment-Create-New.md 20和19的在rollerBall上一样&#xff1a;https://github.com/Unity-Technologies/ml-ag…

vuepress-yarn-nodes-静态网页_个人博客搭建

nodes官网&#xff1a;https://nodejs.org/en 先下载nodes进行安装&#xff0c;一般nodes会自带包管理器npm&#xff0c;注意npm与nodes的对应关系&#xff0c;除了npm之外还有yarn包管理器&#xff0c;一般会用npm安装这个包 npm install --global yarnnpm降低版本的方法 np…

NC65 集团业务参数 GLS01参数值的默认值作用是什么?

NC65 集团业务参数 GLS01参数值的默认值作用是什么&#xff1f; 用在总账系统的所有账簿。如果设置的期间个数大于12&#xff0c;还得要求所查询的账表支持跨年查询&#xff0c;比如科目余额表&#xff0c;不支持跨年&#xff08;注意&#xff1a;这里说的不支持跨年是指余额为…

成都建博会:家居行业数字营销金点子 句句戳心坎,先收藏

四月&#xff0c;不仅是人间最美天&#xff0c;也是第二季度的开始。随着气温上升&#xff0c;行业进入了活跃期。对于西南地区的家居行业从业者来说&#xff0c;来一趟一年一度的成都建博会&#xff0c;总能获得无尽的灵感&#xff0c;对后续更加充满期待。而与同行的交流&…

java-word模板转化为pdf

文章目录 一、引入包1.1在pom引入1.2 因为我们的项目是打包成jar,所以以上方法在本地idea运行没有问题&#xff0c;linux系统不行1.2.1解决方法11.2.2解决方法2 二、配置文件--License.xml--去除水印2.1 license.xml直接放到resources的根目录下即可2.2 工具类 三、调用效果 一…