【JavaScript】ES6新特性(5)

news2024/11/18 11:23:29

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
        // 失败时执行的函数 reject
        let 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.json
        ajax("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)
        })

        // showloading
        Promise.all([pro, pro1, pro2]).then(res => {
            // hideloading
            console.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.coloradmin.cn/o/736969.html

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

相关文章

Linux 进程管理与调度

一、前言 本篇文章是对Liunx的进程管理调度的实验过程记录&#xff0c;读者可以通过这篇文章加深对Liunx中进程管理和调度的理解&#xff0c;本文所使用的操作系统为RHEL 8.0版本&#xff0c;为在Vmware workstation中运行的虚拟机。 二、实验目的 ① 掌握linux进程相关操作 ②…

RabbitMQ学习笔记9 TTL死信队列+延迟队列实战

我们去新建一个交换机&#xff1a; 然后我们再用这种方法直接创建一个队列&#xff1a; 点击bind这样我们的交换机和队列就绑定到一起了。 然后我们要新建普通队列&#xff0c;设置过期时间&#xff0c;指定死信交换机。 发布一条消息。 它会把队列传递到死信队列中去。

Openlayers实战:overlay上播放视频

在企业或者城市等的宣传上,视频能很好的传达出一些信息。 那么在openlayer中如何展示视频呢, 可以通过overlay的方式,点击某一个点,弹出overlay层,展示出视频,并自动播放。下面的实战就能够达到这种效果。 效果图 源代码 /* * @Author: 大剑师兰特(xiaozhuanlan),还…

记忆——记忆宫殿——数字编码

数字编码 数字编码相对简单&#xff0c;与乘法口诀的工作量类似。如果想要达到高手的水平&#xff0c;熟练程度也需要达到乘法口诀的程度。 数字编码的方式是直接创造出数字与形象的唯一的对应关系&#xff0c;然后熟记。 0-9&#xff0c;00-99是什么 最常用的编码是将0-9和…

【C++11】lambda表达式 的定义、性质和用法

定义 Lambda表达式是C11引入的一种函数对象的匿名表示方法。它可以用于定义轻量级的、临时的、内联的函数对象&#xff0c;通常用于函数式编程的场景。 语法结构 Lambda表达式的 基本语法 如下&#xff1a; lambda表达式书写格式&#xff1a;[capture-list] (parameters) m…

java8 新特性 —— Lambda 表达式

我们来看一段老版本的示例代码&#xff0c;其对一个含有字符串的集合进行排序&#xff1a;&#xff08;示例代码创建了一个匿名内部类作为入参。&#xff09; // Collections 工具类提供了静态方法 sort 方法&#xff0c;入参是一个 List 集合&#xff0c;和一个 Comparator 比…

C++栈和队列(详解+刷题)

&#x1f442; 爱要坦荡荡 - 萧潇 - 单曲 - 网易云音乐 &#x1f442; 武侯祠 - 闫东炜 - 单曲 - 网易云音乐 &#x1f442; You Are My Sunshine - Angelika Vee - 单曲 - 网易云音乐 (๑•̀ㅂ•́)و✧ O(∩_∩)O (ง •_•)ง (&#xff5e;﹃&#xff5e;)~zZ …

微鳄三六五软件,企业实现数字化转型仅需2万

关键词&#xff1a;OA办公系统、知识管理系统、群晖NAS 编者按&#xff1a; 疫情对全球经济有着巨大冲击&#xff0c;有调查表明80%的中小企业营收下滑&#xff0c;有30%的中小企业营收减半。天翎特此推出万元即可实现数字化管理方案&#xff0c;为企业提供办公管理、项目管理、…

Canvas.arcTo() 的使用,画一条带圆角的线段,画一个思维导图一基础

Canvas.arcTo() 的使用&#xff0c;画一条带圆角的线段&#xff0c;画一个思维导图一基础 一、方法定义 canvas.arcTo 这个方法还是比较难理解的。因为它不是直观的绘制路径&#xff0c;而是间接的。 它的参数是这样的。 canvas.arcTo(ax,ay,bx,by,radius)它是由两个点和一个…

密码学学习笔记(十):Digital Signatures - 数字签名1

什么是数字签名&#xff1f; 想象一下一下情景&#xff1a; Alice生成两个密钥&#xff1a;一个公钥&#x1d443;&#x1d43e;&#x1d434; & 对应的密钥&#x1d446;&#x1d43e;&#x1d434;, 发布公钥&#xff0c;保留密钥然后Alice使用&#x1d446;&#x1d4…

ARG DEBIAN_FRONTEND=noninteractive作用说明

使用 在Dockerfile中使用ARG指令定义变量并为其指定一个默认值。ARG指令用于在构建过程中传递变量的值。 对于DEBIAN_FRONTENDnoninteractive&#xff0c;它定义了一个名为DEBIAN_FRONTEND的变量&#xff0c;并将其默认值设置为noninteractive。在这个上下文中&#xff0c;no…

【uniapp开发h5】点击复制微信号并自动打开微信应用,类似可以唤起淘宝、知乎应用等

效果展示&#xff1a; 准备工作&#xff1a; 引用jquery.js 和 clipboard.min.js jQuery就不用多说了&#xff0c;而clipboard.min.js 是一个 JavaScript 库&#xff0c;用于实现网页上的复制到剪贴板功能。它提供了一种简单的方式来处理复制操作&#xff0c;无需使用浏览器原…

Ubuntu 包管理的 20 个“apt-get”命令

动动发财的小手&#xff0c;点个赞吧&#xff01; 在引入 apt 命令之前&#xff0c;apt-get 命令是基于 Debian 的 Linux 发行版中使用的主要包管理命令。 使用 apt-get 命令&#xff0c;您可以在系统上安装、删除、升级、搜索和管理软件包。然而&#xff0c;从 Ubuntu 16.04 和…

22运动估计(matlab程序)

1.简述 实验目的 熟悉运动估计的块匹配&#xff08;BMA&#xff09;算法原理&#xff0c;编程实现全搜索算法&#xff08;三步搜索或钻石搜索算法&#xff09;&#xff0c;了解运动估计在混合编码器中的作用。 实验内容 1&#xff09;编写全搜索算法函数&#xff0c;将运动矢量…

使用Llama.cpp在CPU上快速的运行LLM

大型语言模型(llm)正变得越来越流行&#xff0c;但是它需要很多的资源&#xff0c;尤其时GPU。在这篇文章中&#xff0c;我们将介绍如何使用Python中的llama.cpp库在高性能的cpu上运行llm。 大型语言模型(llm)正变得越来越流行&#xff0c;但是它们的运行在计算上是非常消耗资源…

MongoDB教程-5

复制是跨多个服务器同步数据的过程。复制在不同的数据库服务器上提供数据的多个副本&#xff0c;从而提供冗余并提高数据可用性。复制可防止数据库丢失单个服务器。复制还允许您从硬件故障和服务中断中恢复。通过增加数据拷贝&#xff0c;您可以将其中一个用于灾难恢复、报告或…

Spring系列4 -- Bean的作用域和生命周期

目录 1. 案例 2. 作用域定义 2.1 Bean的6种作用域 2.2 设置作用域 3. Sring的执行流程 4. Bean的生命周期 思考: 为什么不是先进行初始化然后再进行设置属性呢? 1. 案例 假设现在有⼀个公共的 Bean&#xff0c;提供给 A ⽤户和 B ⽤户使⽤&#xff0c;然⽽在使⽤的途中…

【面试】Hbase

逻辑模型 1 NameSpace 命名空间&#xff0c;类似于关系型数据库的database概念&#xff0c;每个命名空间下有多个表。Hbase有两个自带的命名空间,分别是hbase和default, hbase中存放的是HBase内置的表, default表是用户默认使用的命名空间。 2 Region 类似于关系型数据库的表…

综合 案例

案例1&#xff1a;淘宝焦点图布局 基本结构 1.大盒子我们类名为: tb-pro淘宝广告 2.里面先放一张图片 3.左右两个按钮用链接。左箭头prev 右箭头 next 4.底侧小圆点用ul 类名为pro-nav 注意&#xff1a; 1.如果一个盒子既有left属性也有right属性&#xff0c;则默认会执行lef…

Nvidia Jetson Orin系列配置教程

Nvidia Jetson Orin系列配置教程包含Orin系列的安装及配置办法&#xff0c;目前最为推荐的办法是通过Nvidia SDK Manager进行安装&#xff0c;详细内容如下&#xff1a; 法1&#xff1a;通过Nvidia SDK Manager进行安装 1.下载工具 前往Nvidia SDK Manager下载工具 2.安装工…