Promise介绍和详解
创始人
2025-05-28 17:00:05
0

Promise

Promise

        - Promise可以帮助我们解决异步中的回调函数的问题

        - Promise就是一个用来存储数据的容器

                它拥有着一套特殊存取数据的方式

                这个方式使得它里边可以存储异步调用的结果

创建promise

// 创建Promise
const promise = new Promise(executor)

是一个回调函数,进一步创建Promise时需要一个exexutor(执行器)为参数,执行器是一个回调函数,进一步调用大概长这个样子

// 创建Promise
const promise = new Promise((resolve, reject) => {})

回调函数再执行时会收到两个参数,两个参数都是函数,第一个函数通常命名为resolve,第二个函数通常会命名为reject,向Promise中存储值得关键就在于这两个函数,可以将想要存储到Promise中的值作为函数的参数传递,

// 创建Promise
const promise = new Promise((resolve, reject) => {resolve("哈哈哈哈")
})
console.log(promise)

两个函数:

  1. resolve用来存储运行正确时的数据
  2. reject用来存储运行出错时的错误信息

我们使用Promise时需要根据不同的情况,调用不同的函数来存储不同的数据;

Promise中存储的主要是异步调用的数据,也就是本来需要回调函数来传递的数据。

在Promise中,可以直接调用异步代码,在异步代码执行完毕后直接调用resolve或reject来执行结果存储到Promise中,这就解决了易怒代码无法设置返回值的情况,如下:

// 创建Promise
const promise = new Promise((resolve, reject) => {setTimeout(() => {resolve("哈哈哈")}, 10000)
})
console.log(promise)

上述代码中setTimeout实现了一个异步调用,定时器会在10秒后执行,并且调用resolve将“哈哈”存储到promise中;

获取Promise中的数据

then

then是Promise的实例方法,通过改方法可以获取到Promise中存储的数据,它需要一个回调函数作为参数,Promise中存储的数据会作为回调函数的实参返回给我们

const promise = new Promise((resolve, reject) => {setTimeout(() => {resolve("哈哈哈")}, 1000)
})promise.then((data) => {console.log(data)  // 打印结果为"哈哈"
})

注意:这种方式只适用于读取通过reslove存储的数据,如果存储数据时出现了错误,或者是通过reject存储的数据,这种方式是无法读取的

const promise = new Promise((resolve, reject) => {// 出错的数据throw new Error("出错了")setTimeout(() => {resolve("哈哈哈")}, 1000)
})promise.then((data) => {console.log(data)  // 打印结果为"哈哈"
})
const promise = new Promise((resolve, reject) => {   setTimeout(() => {// 通过reject来添加reject("哈哈哈")}, 1000)
})promise.then((data) => {console.log(data)  // 打印结果为"哈哈"
})

上述两种情况均无法读取到数据,且控制台会在运行时候报错

第一种Promise的代码出错时,应该为其指定第二个参数来处理数据

第二种通过reject来添加数据时,添加的应该是有问题的数据,而不是正常数据

then的第二个参数依然是一个回调函数,两个回调函数的结构是相同的,不同点在于第一个回调函数在resolve添加数据,即没有异常时候被调用,而第二个函数会在出现错误(或者通过reject存储数据)时调用

const promise = new Promise((resolve, reject) => {   setTimeout(() => {// 通过reject来添加reject("哈哈哈")}, 1000)
})promise.then((data) => {console.log(data)  // 打印结果为"哈哈"
},(err) => {console.log("出错了", err)
})
const promise = new Promise((resolve, reject) => {   throw new Error("主动抛出错误")setTimeout(() => {resolve("哈哈哈")}, 1000)
})promise.then((data) => {console.log(data)  // 打印结果为"哈哈"
},(err) => {console.log("出错了", err)
})

上面的示例中,then的第二个回调函数会执行

执行时异常信息或通过reject返回的数据作为参数传递

开发过程中,then的第二个回调函数通常会用来编写异常        在Promise中维护着两个隐藏的值PromiseResult和PromiseState,PromiseResult是Promise中真正存储值得地方,在Promise中无论是通过resolve、reject还是报错时得异常信息都会存储到PromiseResult中,PromiseState用来表示Promise中值的状态,

Promise一共有三种状态:pending、fulfilled、rejected此时Promise中没有任何值,fulfilled是Promise的完成状态,此时表示值已经正常存储到了Promise中(通过reslove)。rejected表示拒绝,此时表示值是通过reject存储或是执行时出现了错误

当我们调用Promise方法,相当于为Promise设置了一个回调函数,

then中的回调函数不会立即执行,而是在Promise的PromiseState发生变化才会执行。

如果PromiseState从pending变成了fulfilled则then的第一个回调函数执行,且PromiseResult的值作为参数传递给回调函数

如果PromiseState从pending变成了rejected则then的第二个回调函数执行,且PromiseResult的值作为参数传递给回调函数

总结:

Promise中维护了两个隐藏属性:

        PromiseResult

                - 用来存储数据

PromiseState

        - 记录Promise的状态(三种状态)

                pending (进行中)

                fulfilled (完成) 通过resolve存储数据

                rejected  (拒绝,出错了)  出错了或通过reject存储数据时

        - state只能修改一次,修改以后永远不会再变

流程总结:

当Promise创建时,PromiseState初始值为pending

        当通过resolve存储数据时候 PromiseState 变为fulfilled(完成)

                PromiseResult变为存储的数据

        当通过reject存储数据或出错时 PromiseState 变为rejected(拒绝,出错了)

                PromiseResult变为存储的数据 或者 异常对象

当我们通过then读取数据时,相当于为Promise设置了回调函数

        如果PromiseState变为fulfilled,则调用then的第一个回调函数来返回数据

        如果PromiseState变为rejected,则调用then的第二个回调函数来返回数据

 Catch

catch()用法和then类似,但是只需要一个回调函数作为参数

        catch()中的回调函数只会在Promise被拒绝时才调用

        catch()相当于then(null, reson => {} )  即第一个参数为null的then

        catch() 就是一个专门处理Promise异常的方法

const promise = new Promise((resolve, reject) => {   reject("出错了")
})// 出现异常,使用catch来读取数据
promise.catch(err => {console.log(err)
})

处理Promise时,如果没有对Promise中的异常进行处理(无论是then的二参数,还是catch),则异常信息总是会封装到下一步的Promise中进行传递,直到找到异常处理代码的位置,如果没有处理,则报错

这种设计方式使得我们可以在任意位置对Promise的异常进行处理,如下实例

function sum(a, b) {return new Promise((resolve, reject) => {if (Math.random() > 0.7) {throw new Error("出错了")}resolve(a + b)})
}sum(123, 456).then(result => sum(result, 777)).then(result => sum(result, 888)).then(result => console.log(result))

上述示例中,sum函数有几率会出现异常,但我们并不确定何时出现异常,

因为在出现异常后所有的then在异常处理前都不会执行,所以可以将catch写在调用链的最后,这样无论哪一步出现异常,我们都可以在最后统一处理

sum(123, 456).then(result => sum(result, 777)).then(result => sum(result, 888)).then(result => console.log(result)).catch(err => console.log("出错了", 88888))

当然如果我们想在中间处理异常也是可以的,只是需要注意在链式中间处理异常时候,由于后续还有then要执行,所以一点过不要忘了来考虑是否需要在catch中返回一个结果供后续的promise使用:

function sum(a, b) {return new Promise((resolve, reject) => {if (Math.random() > 0.7) {throw new Error("出错了")}resolve(a + b)})
}sum(123, 456).then(result => sum(result, 777)).catch(err => {// 在调用链的中间处理异常console.log("出错了,选择忽略这个错误,重新计算")// 返回一个结果供后续运算return sum(123, 456)}).then(result => sum(result, 888)).then(result => console.log(result))

需要注意的是。在Promise正常执行的情况下如果遇到catch,catch是不会执行的,此时Promise中的结果会自动传递给下一个Promise供后续使用

Finally

  • 无论是正常存储数据还是出现异常了,finally总会执行
  • 通常在finally中定义一些无论Promise正常执行与否都需要处理的工作
  • finally的回调函数不接收任何参数
  • finally的返回值不会成为下一步的Promise中的结果
  • finally只是编写一些必要执行的代码,不会对Promise产生任何实质性的影响

相关内容

热门资讯

【MySQL】锁 锁 文章目录锁全局锁表级锁表锁元数据锁(MDL)意向锁AUTO-INC锁...
【内网安全】 隧道搭建穿透上线... 文章目录内网穿透-Ngrok-入门-上线1、服务端配置:2、客户端连接服务端ÿ...
GCN的几种模型复现笔记 引言 本篇笔记紧接上文,主要是上一篇看写了快2w字,再去接入代码感觉有点...
数据分页展示逻辑 import java.util.Arrays;import java.util.List;impo...
Redis为什么选择单线程?R... 目录专栏导读一、Redis版本迭代二、Redis4.0之前为什么一直采用单线程?三、R...
【已解决】ERROR: Cou... 正确指令: pip install pyyaml
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
Lock 接口解读 前置知识点Synchronized synchronized 是 Java 中的关键字,...
Win7 专业版安装中文包、汉... 参考资料:http://www.metsky.com/archives/350.htm...
3 ROS1通讯编程提高(1) 3 ROS1通讯编程提高3.1 使用VS Code编译ROS13.1.1 VS Code的安装和配置...
大模型未来趋势 大模型是人工智能领域的重要发展趋势之一,未来有着广阔的应用前景和发展空间。以下是大模型未来的趋势和展...
python实战应用讲解-【n... 目录 如何在Python中计算残余的平方和 方法1:使用其Base公式 方法2:使用statsmod...
学习u-boot 需要了解的m... 一、常用函数 1. origin 函数 origin 函数的返回值就是变量来源。使用格式如下...
常用python爬虫库介绍与简... 通用 urllib -网络库(stdlib)。 requests -网络库。 grab – 网络库&...
药品批准文号查询|药融云-中国... 药品批文是国家食品药品监督管理局(NMPA)对药品的审评和批准的证明文件...
【2023-03-22】SRS... 【2023-03-22】SRS推流搭配FFmpeg实现目标检测 说明: 外侧测试使用SRS播放器测...
有限元三角形单元的等效节点力 文章目录前言一、重新复习一下有限元三角形单元的理论1、三角形单元的形函数(Nÿ...
初级算法-哈希表 主要记录算法和数据结构学习笔记,新的一年更上一层楼! 初级算法-哈希表...
进程间通信【Linux】 1. 进程间通信 1.1 什么是进程间通信 在 Linux 系统中,进程间通信...
【Docker】P3 Dock... Docker数据卷、宿主机与挂载数据卷的概念及作用挂载宿主机配置数据卷挂载操作示例一个容器挂载多个目...