JavaScript中的promise

2023-11-13

概述:

promise【承诺】是异步编程的一种解决方案,可以替代传统的解决方案—回调函数和事件,ES6统一了用法,并原生提供了Promise对象,promise是异步编程的一种解决方案。
什么时候我们会来处理异步事件呢?
一种很常见的场景就应该是网络请求了,我们封装一个网络请求的函数,因为不能立即拿到结果,所以不能像简单的1+1=2一样将结果返回所以我们往往会传入另外一个函数,在数据请求成功时,将数据通过传入的函数回调出去。 如果只是一个简单的网络请求,那么这种方案不会给我们带来很大的麻烦,但是当网络请求复杂是,就会出现回调地狱。
在这里插入图片描述
上面代码正常情况下,不会有什么问题,可以正常运行并且获取我们想要的结果,但是,这样的代码难看而且不容易维护【需要将后端打一顿】,我们更加希望的一种更加优雅的方式来进行这种异步操作。使用Promise,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>
        //使用setTimeout
        // setTimeout(()=>{
        //     console.log("Hello world!");
        // },1000)

        //参数->函数(resolve,rekect)
        //resolve,reject本身它们又是函数
        //链式编程
        new Promise((resolve,reject) => {
            //第一次网络请求
            setTimeout(()=>{
                resolve();
            },1000)
        }).then(()=>{
            //第一次拿到结果的处理代码
            console.log("Hello world!");
            console.log("Hello world!");
            console.log("Hello world!");
            return new Promise((resolve,reject)=>{
              //第二次网络请求的代码
              setTimeout(()=>{
               // resolve()

               //失败时候调用reject
               reject('error message')
              },1000)
            })
        }).then(()=>{
            //第二次处理的结果代码
            console.log("Hello vue.js!");
            console.log("Hello vue.js!");
            console.log("Hello vue.js!");
            return new Promise((resolve,reject)=>{
                //第三次网络请求的代码
                setTimeout(()=>{
                    resolve()
                },1000)
            })
        }).then(()=>{
            //第三次处理的代码
            console.log("Hello Promise!");
            console.log("Hello Promise!");
            console.log("Hello Promise!");
        }).catch((err)=>{
            //
            console.log(err);
        })
        // new -> 构造函数(1.保存了一些信息,2.传入的函数)
        //在执行传入的回调函数时,会传入两个参数,resolve,reject,本身又是函数
    </script>
</body>
</html>

效果:
在这里插入图片描述

简单来说,promise就是,你女朋就要过生日了,然后你承诺她在她的生日的时候会给她买一口红,好了你女朋友获得了你给她的承诺,但是,天知道这个承诺会不会实现,位置的因素很多,不能绝对认为你给你女朋友的promise就一定能实现。

所以Promise 有了三种可能的状态:

1.pending(待定的):你女朋友不知道你能不能给她口红,她只能等待她生日的时候的到来。等待状态,比如正在进行网络请求,或者定时器没有到时间。

2.fulfilled(已解决/以实现):到了生日那天你真的给你女朋友一支口红,你实现了你女朋友的承诺。满足状态,当我们主动回调了resolve的时候,就处于该状态,并且回调.then()。

3.rejected(已拒绝/没有实现):你忘了你女朋友的生日,所以没有送口红给你女朋友。拒绝状态,当我们主动回调了reject时,就处于该状态,并且会回调.catch()。
在这里插入图片描述
例子

 <script>
        new Promise((resolve,reject)=>{
            setTimeout(()=>{
                resolve('hellow vue.js')
                //reject("error message")
            },1000)
            //调用resolve的时候执行函数1,调用reject的时候执行函数2
        }).then(data =>{
            console.log(data);
        },err=>{
            console.log(err);
        })
    </script>

执行reslove的时候调用than里面的函数1,执行reject的时候执行函数2
在这里插入图片描述
在这里插入图片描述
Promise的链式调用
在我们看到promise的流程图的时候,发现无论是then还是catch都可以返回一个Promise对象,所以promise代码可以进行链式调用,我们直接通过promise包装了一下数据,将promise对象返回了
Promise.resolve():将数据包装成promise对象,并且在内部回调resolve()函数。
Promise.reject():将数据包装成promise对象,并且在内部回调reject()函数。

三层处理链式调用例子

 <script>
        //网络请求:aaa -> 自己处理(10行)
        //处理:aaa111 -> 自己处理(10行)
        //处理:aaa111222-> 自己处理

        new Promise((resolve,reject)=>{
            setTimeout(() => {
                resolve("aaa");
            },1000)
        }).then(res => {
            //1.自己处理10行代码
            console.log(res,"第一层的10行处理代码");

            //2.对结果进行第一次处理
            return new Promise((resolve)=>{
                resolve(res+'111')
            })
        }).then(res =>{
            console.log(res,"第二层10行处理代码");
            return new Promise(resolve=>{
                resolve(res+'222')
            })
        }).then(res=>{
            console.log(res,"第三层的10行处理代码")
        })
   </script>

其中than返回的直接是一个promise对象,不需要重新new promise对象,简写方法如下:

<script>
        //网络请求:aaa -> 自己处理(10行)
        //处理:aaa111 -> 自己处理(10行)
        //处理:aaa111222-> 自己处理

        new Promise((resolve,reject)=>{
            setTimeout(() => {
                resolve("aaa");
            },1000)
        }).then(res => {
            //1.自己处理10行代码
            console.log(res,"第一层的10行处理代码");

            //2.对结果进行第一次处理
            return Promise.resolve(res+'111')
        }).then(res =>{
            console.log(res,"第二层10行处理代码");
            return Promise.resolve(res+'222')
        }).then(res=>{
            console.log(res,"第三层的10行处理代码")
        })
   </script>

更简洁的写法,直接将结果return ,到时候then内部将会对promise进行包装,直接省略return.promise写法

<script>
        //网络请求:aaa -> 自己处理(10行)
        //处理:aaa111 -> 自己处理(10行)
        //处理:aaa111222-> 自己处理

        new Promise((resolve,reject)=>{
            setTimeout(() => {
                resolve("aaa");
            },1000)
        }).then(res => {
            //1.自己处理10行代码
            console.log(res,"第一层的10行处理代码");

            //2.对结果进行第一次处理
            return res+'111'
        }).then(res =>{
            console.log(res,"第二层10行处理代码");
            return res+'222'
        }).then(res=>{
            console.log(res,"第三层的10行处理代码")
        })
   </script>

代码效果:

在这里插入图片描述
如果有一层reject的时候的写法:

<script>
        //网络请求:aaa -> 自己处理(10行)
        //处理:aaa111 -> 自己处理(10行)
        //处理:aaa111222-> 自己处理

        new Promise((resolve,reject)=>{
            setTimeout(() => {
                resolve("aaa");
            },1000)
        }).then(res => {
            //1.自己处理10行代码
            console.log(res,"第一层的10行处理代码");

            //2.对结果进行第一次处理
            return Promise.reject("err")
        }).then(res =>{
            console.log(res,"第二层10行处理代码");
            return res+'222'
        }).then(res=>{
            console.log(res,"第三层的10行处理代码")
        }).catch(err => {
            console.log(err);
        })
   </script>

最简洁的报错写法 throw语句,直接throw 'error message’

   <script>
        //网络请求:aaa -> 自己处理(10行)
        //处理:aaa111 -> 自己处理(10行)
        //处理:aaa111222-> 自己处理

        new Promise((resolve,reject)=>{
            setTimeout(() => {
                resolve("aaa");
            },1000)
        }).then(res => {
            //1.自己处理10行代码
            console.log(res,"第一层的10行处理代码");

            //2.对结果进行第一次处理
            throw 'error message'
        }).then(res =>{
            console.log(res,"第二层10行处理代码");
            return res+'222'
        }).then(res=>{
            console.log(res,"第三层的10行处理代码")
        }).catch(err => {
            console.log(err);
        })
   </script>

效果:
在这里插入图片描述
Promise - all方法使用
在这里插入图片描述
Promise.all是在所有的Promise对象都执行完成之后resolve。参数是一个数组,数组的每一项都是一个Promise对象就可以。
什么情况下使用呢?
当有一个需求,必须两个结果都拿到手才进行下一步操作的时候使用!
在这里插入图片描述
如上代码通过改变两个变量判断一个需求中的两个状态是否完成,显得很繁琐,promise直接包装两个异步请求,它可以在两个异步请求都完成得时候在一个地方进行回调!
格式:

Promise.all(结果,数组可迭代对象)

在这里插入图片描述
使用setTimeout进行模拟:

 <script>
        //Promise.all(结果,数组可迭代对象)
        Promise.all([
            new Promise((resolve,reject)=>{
                setTimeout(()=>{
                    resolve({name:"wuyong",age:18});
                },2000)
            }),
            new Promise((resolve,reject)=>{
                setTimeout(()=>{
                    resolve("resolve2");
                },1000)
            })
        ]).then(results =>{
            console.log(results);
        })
    </script>

显示结果:
在这里插入图片描述
完结~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JavaScript中的promise 的相关文章

  • 打印带有图像的 html(每个图像在单独的页面上)

    我有一个带有图像的 HTML img img img img 打印时 我希望每个图像都位于单独的页面上 根据打印尺寸 现在我把图像从中间切掉了 有什么办法可以解决吗 您可以尝试以下方法 p p
  • 将 JavaScript 数组转换为具有属性的数组

    我有一个像这样的数组从服务器返回响应 111 1010 111 1010 1010 我想将其转换为 JavaScript JSON 如下所示 branch 111 branch 1010 branch 111 branch 1010 bra
  • 通过 declarativeNetRequest + extensionPath 重定向时获取原始 URL

    我需要在导航时但在用户从使用设置的规则重定向之前获取 chrome 选项卡的 urldeclarativeNetRequest 目前 用户可以使用上下文菜单添加规则 当尝试访问过滤的主机时 它将被重定向到内部扩展页面 chrome cont
  • 为什么我会收到此 Javascript 错误“连接未定义”?

    我不确定为什么会收到此错误 connection is not defined document getElementById flashTest sendValFromHtml connection value 这是我的代码 functi
  • 如何在 的每四个循环项之后添加

    我想在循环中的每第四个数字项之后退出循环 我想创建一个二十人的名单 在每一个tr应该是4个人 So I want to break from the loop after every 4th number of loop My one tr
  • 图表js不显示

    我正在尝试使用 Charts js 创建一个简单的折线图 当我运行下面的代码时 没有出现图表 我究竟做错了什么 我正在关注这个教程http www chartjs org docs latest getting started http w
  • 在 JSON 数组中按属性查找对象

    我在获取 JSON 数据中的字符串时遇到问题 格式如下 name Alice age 20 id David last 25 id John last 30 有时它会一起改变位置 John从第三名到第二名 name Alice age 20
  • 在多个 angular.js 应用程序之间共享单个服务

    我正在构建一个电子商务网站 基于 shopify 并且使用多个小型 angularjs 应用程序来处理诸如快速购物车 愿望清单 过滤产品和其他一些较小项目之类的事情 我最初使用了一个大型应用程序 具有路由和所有内容 但当我没有完整的 RES
  • 将 MVC 操作结果发送到打印机

    我有一个带有操作的控制器 SomeController ActionToBePrinted ActionToBePrinted 返回一个 html 视图 当按下按钮时 从普通的 mvc razor 视图调用此操作 当按下按钮时 我将如何将视
  • 检测 JavaScript 版本

    如何检测浏览器支持的 JavaScript 版本 如果有 我想检查 ECMAScript 3 ECMAScript 5 和 ECMAScript 6 注意 我想避免已弃用的language tag 这里有一个很好的参考给你 http www
  • Android键盘点击搜索输入时出现和消失

    我在用谷歌地图 Js API当我搜索一个地方时 我的输入搜索栏工作正常 当我通过 iPhone 设备使用它时 它也工作得很好 但是当我通过Android 设备然后键盘立即出现和消失 我已经找到了一些关于当我按下搜索栏时 android 键盘
  • .then(functionReference) 和 .then(function(value){return functionReference(value)}) 之间有区别吗?

    给定一个用于处理的命名函数Promise value function handlePromise data do stuff with data return data a 传递命名函数handlePromise作为参考 then pro
  • 如何从矩形点计算旋转角度?

    我有4分1 2 3 4闭合一个矩形 这些点按以下方式排列在数组中 x1 y1 x2 y2 x3 y3 x4 y4 我遇到的问题是矩形可以旋转一定角度 如何计算原始点 灰色轮廓 和角度 我试图在 javascript css3 transfo
  • c3js数据标签的位置

    有没有可能的方法来更改数据上方标签的位置c3条形图 在官方文档中 很好地解释了如何通过操作 y 和 x 整数来更改 x 和 y 测量轴上标签的位置 但我没有找到任何数据标签 我试图用简单的方式指出它d3其上c3是基于但是console lo
  • jQuery.ajax() 记录 HTTP 请求

    我有一个发送 HTTP POST 请求的函数 我想记录它以进行调试 这是函数 function serverRequest URL DATA callback ajax url URL type POST dataType text con
  • 同源政策目的可疑

    正如我所读到的 同源策略是防止源自 邪恶 域 A 的脚本向 良好 域 B 发出请求 换句话说 跨站点请求伪造 玩了一下我了解到的Access Control Allow Origin标头和CORS据我了解 它允许从好域 B 指定服务器 域
  • 如何防止 CSS 或 jQuery 中单词和标点符号之间的换行

    我在一个段落中有一些文字 我的问题是 当标点符号位于单词末尾时 有时可以换行到下一行 像这样 This is the text This is a new line 我可以用 CSS 或 jQuery 解决这个问题吗 如果您不在单词和标点符
  • 通过排列四个给定数字找到最大可能时间 HH:MM

    我最近为了工作晋升而参加了编码测试 这是我真正遇到的任务之一 我想知道什么是最好的方法来做到这一点 我使用了大量的 if 和 if else 这不是最干净的解决方案 但完成了工作 我被问到的问题是 将 4 个数字格式化为 24 小时时间 0
  • 如何清除画布中图像上的矩形

    我需要清除画布中图像上绘制的矩形 而不损坏现有图像 我可以绘制小矩形点并将其清除 但问题是 当我清除矩形时 它在图像上仍保留为白色小斑点 有人可以告诉我如何清除图像上的矩形而不损坏现有图像 我使用了以下方法来清除矩形 但没有用 1 cont
  • 检测未定义的对象属性

    如何检查 JavaScript 中的对象属性是否未定义 检查属性值是否为特殊值的常用方法undefined is if o myProperty undefined alert myProperty value is the special

随机推荐

  • Message": "请求的资源不支持 http 方法“GET”

    今天用postman测试后端api 总是报错 下面是问题解决方案 一 测试方法 public ApiResult Get int id ApiResult result new ApiResult result data 我是Get方法返回
  • Java调用jython

    Java调用jython 因为工作需要 需要在Java Jvm 进程内调用Python脚本 下了Jython练练手 脚本语言看着真别扭啊 若干年前写自动化测试工具时也用过python一小阵子 但基本忘光光了 好了 直奔主题 前提 1 sun
  • Linux如何给服务器增加白名单

    1 查看系统白名单配置 iptables L n 2 增加白名单 19 40 145 140 是需要增加的服务器IP iptables I INPUT s 19 40 145 140 32 p tcp j ACCEPT 注 I I是i的大写
  • oracle 函数使用方法----replace函数

    例 sql语句如下 select from cen sys TB DIC JDLX t 查询结果如下 需求 需要获取字段 PID 的值并 新增一个字段 PNAME PNAME的值为字段PID去掉 市平台前置机 剩下的字段 实现 select
  • 后端返回parentId,前端处理成children嵌套数据

    rouyi 的 vuetree函数结合elementui el table组件使用 把有parentId和id结构的数据处理成children嵌套数据 字段名称不一致 可以设置 vuetree函数 构造树型结构数据 param data 数
  • html 调用ActiveX

    html网页调用ActiveX控件时 要获取到ActiveX的ClassID 这个ClassID是注册到系统里的 而不是工程中的uuid 下图为uuid 正确的是在注册表的HKEY CLASSES ROOT中查找你的工程名的 项 找到后 其
  • flink state ttl 清理逻辑(截止到flink1.8之前的逻辑)

    在我们开发Flink应用时 许多有状态流应用程序的一个常见要求是自动清理应用程序状态以有效管理状态大小 或控制应用程序状态的访问时间 TTL Time To Live 功能在Flink 1 6 0中开始启动 并在Apache Flink中启
  • openwrt golang mysql_golang1.9编译openwrt运行程序 ,window7下liteide编译

    网上看了好多资料发现都很过时了 基本都是用的https github com gomini go mips32编译的 但是go1 9早就支持mips了 设置好编译参数 开始build 这时在go pkg下会出现linux mips目录 就是
  • Thumb / Thumb-2 / ThumbEE

    本文转载至 http zh wikipedia org wiki ARM E6 9E B6 E6 A7 8B Thumb 较新的ARM处理器有一种16 bit指令模式 叫做Thumb 也许跟每个条件式运行指令均耗用4位的情形有关 在Thum
  • 问题定位及解决方案

    1 视频沉浸页快速滑动后 必现不能向下划动 复现步骤 进入视频沉浸页 快速向下划动 滑动到第一页最后一个时 不能再向下划动 解决步骤 1 确定请求API mtop aliexpress ugc feed video list 2 找到触发请
  • uniapp开发小程序,编译时报错Cannot read property ‘forceUpdate‘ of undefined的解决方案

    1 这个报错 主要是没有在uniapp的开发平台为这个应用注册一个appid 2 登录uniapp开发平台 https dev dcloud net cn 注册成为开发者 并创建一个应用 此应用的名称要与本地的项目的名称一致 3 重现获取u
  • Android开发---Fragment可见/不可见时的生命周期回调函数

    Fragment可见 不可见时的生命周期回调函数 项目中经常会碰到 需要在fragment失去焦点和获得焦点的方法中进行一些设置 但是fragment没有onpause 和onResume 方法 你重写的这两个方法 都是fragment依附
  • python安装

    Python 环境搭建 本章节我们将向大家介绍如何在本地搭建Python开发环境 Python可应用于多平台包括 Linux 和 Mac OS X 你可以通过终端窗口输入 python 命令来查看本地是否已经安装Python以及Python
  • ORA-32021: parameter value longer than 255 characters 解决方法

    在增加节点完后 用dbca 添加数据库实例时 报ORA 32021 parameter value longer than 255 characters 错误 oraagent log 2011 10 24 09 18 32 724 USR
  • 框架学习笔记——Spring

    Spring 文章目录 Spring 1 Spring简介 1 1 框架的主要特征 1 2 Spring的主要特点 1 3 组成 2 Spring之控制反转 IOC 2 1 百科 2 2 两种方式 2 3 依赖注入 推导 2 3 1 新建一
  • Centos7.5安装应用服务教程 ---- jdk1.8安装教程

    1 下载jdk1 8压缩包 建议装在 usr local目录下 2 解压 tar zxvf jdk 8u301 linux x64 tar gz 3 配置环境变量 修改文件配置 vi vim etc profile 在文件底部加入以下配置
  • C++中queue使用详细说明

    一 queue 的介绍 queue 翻译为队列 在 STL 中主要则是实现了一个先进先出的容器 二 queue 的定义 单独定义一个 queue queue
  • linux开放tomcat8080端口,防火墙开启/关闭/状态查询

    linux开放tomcat8080端口 防火墙开启 关闭 状态查询 最终效果 开放8080端口成功访问tomcat页面 要实现开放端口8080有两种方式 仅限于我所知道的 条条大路通罗马 能实现功能就行 废话不多说上干货 一是单独开放808
  • github 如何删除不需要的项目(两种方法)

    在Github上删除项目是一项非常基本的操作 但是对于很多使用者来说 却可能会因为缺乏经验而无从下手 如果你也处于这个情况 那么这篇文章就为你提供了一些详细的指导 删除Github上的项目可以采用两种方式 通过网站进行删除 或者通过Git客
  • JavaScript中的promise

    概述 promise 承诺 是异步编程的一种解决方案 可以替代传统的解决方案 回调函数和事件 ES6统一了用法 并原生提供了Promise对象 promise是异步编程的一种解决方案 什么时候我们会来处理异步事件呢 一种很常见的场景就应该是