【JavaScript】ES6新特性(5)

16. Promise

Promise 是异步编程的一种解决方案,比传统的解决方案回调函数, 更合理和更强大

ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象

  • 指定回调函数方式更灵活易懂
  • 解决异步 回调地狱 的问题

16.1 回调地狱

  • 当一个回调函数嵌套一个回调函数的时候
  • 就会出现一个嵌套结构
  • 当嵌套的多了就会出现回调地狱的情况
  • 比如发送三个 ajax 请求
    • 第一个正常发送
    • 第二个请求需要第一个请求的结果中的某一个值作为参数
    • 第三个请求需要第二个请求的结果中的某一个值作为参数
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>回调地狱</title>
</head><body><script>function ajax(url, success, failcb) {setTimeout(() => {success("11111")}, 1000)}ajax({url: '我是第一个请求',success(res) {// 现在发送第二个请求ajax({url: '我是第二个请求',data: { a: res.a, b: res.b },success(res2) {// 进行第三个请求ajax({url: '我是第三个请求',data: { a: res2.a, b: res2.b },success(res3) {console.log(res3)}})}})}})</script>
</body></html>

回调地狱,其实就是回调函数嵌套过多导致的

当代码成为这个结构以后,已经没有维护的可能了

16.2 Promise使用

Promise 是一个对象,可以获取异步操作的消息

语法:

new Promise(function (resolve, reject) {// resolve 表示成功的回调// reject 表示失败的回调
}).then(function (res) {// 成功的函数
}).catch(function (err) {// 失败的函数
})
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Promise 使用</title>
</head><body><script>// promise// 假设异步处理// 成功时执行的函数 resolve// 失败时执行的函数 rejectlet pro = new Promise(function (resolve, reject) {// 执行器函数setTimeout(() => {// 假设成功resolve()}, 1000)})pro.then(() => {console.log("奖金");}, () => {console.log("没有");})let pro1 = new Promise(function (resolve, reject) {// 执行器函数setTimeout(() => {// 假设失败reject()}, 1000)})pro1.then(() => {console.log("奖金");}, () => {console.log("没有");})let pro2 = new Promise(function (resolve, reject) {// 执行器函数setTimeout(() => {// 假设成功,设置参数// resolve(1000)// 假设失败,设置参数reject("1111")}, 1000)})pro2.then((res) => {console.log("奖金",res);}).catch((err) => {console.log("没有", err);})</script>
</body></html>

在这里插入图片描述

16.3 Promise 对象的状态

Promise 对象通过自身的状态,来控制异步操作

  • Promise 实例具有三种状态

    • 异步操作未完成(pending)
    • 异步操作成功(fulfilled)
    • 异步操作失败(rejected)
  • 这三种的状态的变化途径只有两种

    • 从“未完成”到“成功”
    • 从“未完成”到“失败”

一旦状态发生变化,就凝固了,不会再有新的状态变化
这也是 Promise 这个名字的由来,它的英语意思是“承诺”,一旦承诺成效,就不得再改变了
这也意味着,Promise 实例的状态变化只可能发生一次

  • 因此,Promise 的最终结果只有两种
    • 异步操作成功,Promise 实例传回一个值(value),状态变为fulfilled
    • 异步操作失败,Promise 实例抛出一个错误(error),状态变为rejected

在这里插入图片描述

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Promise 对象的状态</title>
</head><body><script>let pro = new Promise(function (resolve, reject) {// 执行器函数setTimeout(() => {// 两个函数放进同时执行// 假设成功,设置参数resolve(1000)// 假设失败,设置参数reject("1111")}, 1000)})pro.then((res) => {console.log("奖金", res);}).catch((err) => {console.log("没有", err);})</script>
</body></html>

在这里插入图片描述

16.4 Promise的链式调用

发送一个请求的处理方式

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>function ajax(url) {return new Promise((resolve, reject) => {let xhr = new XMLHttpRequest()xhr.open("get", url, true)xhr.send()xhr.onreadystatechange = function () {if (xhr.readyState === 4) {if (xhr.status >= 200 && xhr.status < 300) {// resolve(xhr.responseText)// JSON 字符形式resolve(JSON.parse(xhr.responseText))} else {reject(xhr.responseText)}}}})}ajax("65.json").then(res => {console.log(res);}).catch(err => {console.log(err);})// 传入错误的 1.jsonajax("1.json").then(res => {console.log(res);}).catch(err => {console.log(err);})</script>
</body></html>

在这里插入图片描述

连续发送两个请求的处理方式

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Promise的链式调用</title>
</head><body><script>let pro = new Promise(function (resolve, reject) {// 执行器函数setTimeout(() => {// 假设成功resolve(1000)// reject("no 1111")}, 1000)})pro.then((res) => {console.log("奖金1", res);// 如果 return 非 promise 类型,将是 pending 到 fulfilled 的状态//如果return promise类型,根据这个新的promise对象的结果,// 决定 pending 到 fulfilled 的状态还是 pending 到 rejected 的状态}).then((res) => {console.log("奖金2", res);}).catch((err) => {console.log("没有", err);})// 打印出来的是 奖金1 1000 奖金2 undefined// 为什么不是打印 奖金1 1000 就冻结了状态// 因为 第一个执行完返回的时没具体写返回什么,所以是 undefined,// 然后再次执行 then 和 catch语句let pro1 = new Promise(function (resolve, reject) {// 执行器函数setTimeout(() => {// 假设成功resolve(1000)// reject("no 1111")}, 1000)})pro1.then((res) => {console.log("奖金3", res);return res// 如果 return 非 promise 类型,将是 pending 到 fulfilled 的状态//如果return promise类型,根据这个新的promise对象的结果,// 决定 pending 到 fulfilled 的状态还是 pending 到 rejected 的状态}).then((res) => {console.log("奖金4", res);}).catch((err) => {console.log("没有", err);})</script>
</body></html>

在这里插入图片描述

Promise的链式调用

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Promise的链式调用</title>
</head><body><script>function ajax(url) {return new Promise((resolve, reject) => {let xhr = new XMLHttpRequest()xhr.open("get", url, true)xhr.send()xhr.onreadystatechange = function () {if (xhr.readyState === 4) {if (xhr.status >= 200 && xhr.status < 300) {// resolve(xhr.responseText)// JSON 字符形式resolve(JSON.parse(xhr.responseText))} else {reject(xhr.responseText)}}}})}ajax("65.json").then(res => {console.log(res);return ajax("1.joson")}).then(res => {console.log(res);}).catch(err => {console.log(err);})</script>
</body></html>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gokrqyw6-1684742150263)(D:\document\ES6-ES13\ES6-ES13笔记图片\image-20230407201912622.png)]

16.5 Promise.all

Promise.all() 方法用于将多个 Promise 实例,包装成一个新的 Promise 实例

const p = Promise.all([p1, p2, p3]);
  • p 的状态由p1,p2,p3 决定,分成两种情况
    • 只有p1p2p3的状态都变成fulfilledp的状态才会变成fulfilled,此时p1p2p3的返回值组成一个数组,传递给p的回调函数
    • 只要p1p2p3之中有一个被rejectedp的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Promise.all</title>
</head><body><script>let pro = new Promise(function (resolve, reject) {// 执行器函数setTimeout(() => {resolve(1000)}, 1000)})let pro1 = new Promise(function (resolve, reject) {// 执行器函数setTimeout(() => {resolve(2000)}, 1000)})let pro2 = new Promise(function (resolve, reject) {// 执行器函数setTimeout(() => {resolve(3000)}, 1000)})// showloadingPromise.all([pro, pro1, pro2]).then(res => {// hideloadingconsole.log(res);}).catch(err => {console.log(err);})</script>
</body></html>

在这里插入图片描述

16.6 Promise.race

Promise.race()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例

const p = Promise.race([p1, p2, p3]);

上面代码中,只要p1p2p3之中有一个实例率先改变状态,p的状态就跟着改变

那个率先改变的 Promise 实例的返回值,就传递给p的回调函数

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Promise.race</title>
</head>
<body><script>let pro = new Promise(function (resolve, reject) {// 执行器函数setTimeout(() => {resolve(1000)}, 1000)})let pro1 = new Promise(function (resolve, reject) {// 执行器函数setTimeout(() => {resolve(2000)}, 2000)})let pro2 = new Promise(function (resolve, reject) {// 执行器函数setTimeout(() => {resolve(3000)}, 3000)})Promise.race([pro, pro1, pro2]).then(res => {console.log(res);}).catch(err => {console.log(err);})// 运行结果:1000// 因为第一个先完成操作,改变了状态,// 就直接返回第一个完成的 promise 的返回值</script>
</body>
</html>

超时,可以用于当服务器挂掉或者超时了应做的处理

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Promise.race</title>
</head><body><script>let pro = new Promise(function (resolve, reject) {// 执行器函数setTimeout(() => {resolve("成功的结果")}, 30000)})let pro1 = new Promise(function (resolve, reject) {// 执行器函数setTimeout(() => {reject(2000)}, 2000)})Promise.race([pro, pro1]).then(res => {console.log(res);}).catch(err => {console.log(err, "超时了");})// 运行结果:2000 '超时了'// 因为第一个响应时间过长,执行了第二个// 就直接返回第二个的 的 reject 的返回值</script>
</body></html>

GitHub代码
gitee代码

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

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

相关文章

并发编程 - Event Bus 设计模式

文章目录 Pre设计CodeBus接口自定义注解 Subscribe同步EventBus异步EventBusSubscriber注册表RegistryEvent广播Dispatcher 测试简单的Subscriber同步Event Bus异步Event Bus Pre 我们在日常的工作中&#xff0c;都会使用到MQ这种组件&#xff0c; 某subscriber在消息中间件上…

AIGC - Stable Diffusion 的 AWPortrait 1.1 模型与 Prompts 设置

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/131565908 AWPortrait 1.1 网址&#xff1a;https://www.liblibai.com/modelinfo/721fa2d298b262d7c08f0337ebfe58f8 介绍&#xff1a;AWPortrai…

使用LiteSpeed缓存插件将WordPress优化到100%的得分

页面速度优化应该是每个网站所有者的首要任务&#xff0c;因为它直接影响WordPress SEO。此外&#xff0c;网站加载的时间越长&#xff0c;其跳出率就越高。这可能会阻止您产生转化并为您的网站带来流量。 使用正确的工具和配置&#xff0c;缓存您的网站可以显着提高其性能。因…

Spring系列3 -- 更简单的读取和存储对象

前言 上一篇章总结了,Spring的创建与使用,通过创建Maven项目配置Spring的环境依赖,创建Spring框架的项目,然后通过在Resource目录下创建Spring-config.xml配置文件,添加<bean></bean>标签将我们需要的bean对象注入到容器中,然后通过ApplicationContext获取Spring上…

web服务端接收多用户并发上传同一文件,保证文件副本只存在一份(附go语言实现)

背景 对于一个文件服务器来说&#xff0c;对于同一文件&#xff0c;应该只保存一份在服务器上。基于这个原则&#xff0c;引发出本篇内容。 本篇仅阐述文件服务器在同一时间接收同一文件的并发问题&#xff0c;这种对于小体量的服务来说并不常见&#xff0c;但是最好还是要留…

文本分析-使用Python做词频统计分析

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

【滑动窗口】209. 长度最小的子数组

209. 长度最小的子数组 解题思路 滑动窗口设置前后指针滑动窗口内的元素之和总是大于或者等于s滑动窗口的起始位置: 如果窗口的值大于等于s 窗口向前移动窗口结束位置:for循环的j class Solution {public int minSubArrayLen(int target, int[] nums) {int left 0;// 滑动窗口…

学习系统编程No.28【多线程概念实战】

引言&#xff1a; 北京时间&#xff1a;2023/6/29/15:33&#xff0c;刚刚更新完博客&#xff0c;目前没什么状态&#xff0c;不好趁热打铁&#xff0c;需要去睡一会会&#xff0c;昨天睡的有点迟&#xff0c;然后忘记把7点到8点30之间的4个闹钟关掉了&#xff0c;恶心了我自己…

使用 Rust 实现连接远程 Linux 服务器、发送文件、执行命令

使用 Rust 实现连接远程 Linux 服务器、发送文件、执行命令 文章目录 使用 Rust 实现连接远程 Linux 服务器、发送文件、执行命令一、Rust 概述使用场景优点缺点 二、功能实现1、代码2、运行日志3、服务器文件 一、Rust 概述 Rust 已经听了无数遍&#xff0c;我很清楚它很强&am…

LVS-DR集群

目录 一、构建LVS-DR集群的步骤 实验环境准备&#xff1a; 1、配置负载调度器&#xff08;192.168.40.200&#xff09; 1.1 配置虚拟 IP 地址&#xff08;VIP&#xff1a;192.168.40.190&#xff09; 1.2 调整 proc 响应参数 1.3 配置负载分配策略 2. 部署共享存储&#xf…

Elasticsearch 基本使用(五)查询条件匹配方式(query query_string)

查询条件匹配方式 概述querytermtermsrangematch_allmatchmatch 匹配精度问题 match_phrasematch_pharse_prefixmatch_bool_prefixmulti_match query_string简单查询一个字段在多个字段上应用同一个条件 &#xff08;类似multi_match&#xff09;在所有字段上应用同一个条件 &a…

html掉落本地图片效果

实现一个加载本地图片并掉落的html页面。 说明 将DuanWu.html与zongzi_1.png, zongzi_2.png, zongzi_3.png, yadan.png4张图片放在同一个目录下&#xff0c;然后双击打开DuanWu.html即可。 使用Chrome或Microsoft Edge浏览器打开 若使用IE浏览器打开&#xff0c;下方会出现In…