前端javascript Promise使用方法详解(非常全面)

news2024/12/24 10:01:35

在这里插入图片描述

✨✨ 欢迎大家来到景天科技苑✨✨

🎈🎈 养成好习惯,先赞后看哦~🎈🎈

所属的专栏:前端零基础教学,实战进阶
景天的主页:景天科技苑

文章目录

  • Promise对象
    • (1)回调函数
    • (2)promise基本语法
    • (3)then函数
    • (4)Promise链式应用

Promise对象

  • Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。
    它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。
  • Promise 是一个 ECMAScript 6 提供的类,目的是更加优雅地书写复杂的异步任务。
  • Promise是一个构造函数,通过new来实例化,主要解决异步编程。
  • 在 ES2015 中,Promise 诞生了。Promise 成功解决了回调函数嵌套调用和错误跟踪、回调函数控制权等问题。
  • 一个Promise对象有三种状态:pending(等待中)、fulfilled(已成功)或rejected(已失败)。当Promise对象处于pending状态时,它表示尚未完成,但可能会在未来某个时间完成。

new Promise(function(resolve,reject){
})
如果new Promise里面函数的参数 resolve和reject都没有执行,promise的状态就是pending状态,resolve执行了,就是fulfilled。reject执行了就是rejected状态

任何一门技术的出现,都是为了解决问题,他的出现是怎么把问题解决好的。我们重点要关注这一点
Promise出现之前,异步用的就是回调函数

(1)回调函数

了解promise应该先懂回调,简单理解回调函数能够实现异步编程(可以控制函数调用顺序)。紧接着你应该知道回调地狱,或者函数瀑布,就类似如下的代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script>
        //
        setTimeout(function () {
            console.log("apple");
            setTimeout(function () {
                console.log("banana");
                setTimeout(function () {
                    console.log("cherry");
                }, 1000);
            }, 2000);
        }, 3000);
        console.log("下一个操作")
    </script>
</head>
<body>


</body>
</html>

setTimeout是异步操作,由于setTimeout里面的操作都需要等待,因此我们得预期效果是 先打印 下一个操作,然后3秒后打印 apple, 在等2秒后打印 banana, 再过1秒打印 cherry
我们看下控制台,结果如预期
在这里插入图片描述

我们可以把这三个操作想象成ajax向后端发送请求

进阶模拟更像ajax请求
apple请求回来,接着走后续操作
banana请求回来,接着走后续操作
在这里插入图片描述

结果如预期
在这里插入图片描述

目前这种效果是没问题的
但是,多的话,代码已经没法读了,地狱回调,已经无法直视
在这里插入图片描述

Promise 的出现就能够将上面嵌套格式的代码变成了较为有顺序的从上到下风格的代码。
然后看下promise的异步实现

(2)promise基本语法

new Promise(function(resolve, reject) { });

  • Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。
  • Promise 构造函数只有一个参数,这个参数是一个函数,这个函数在构造之后会直接被异步运行,所以我们称之为起始函数。
    起始函数包含两个参数 resolve 和 reject。异步任务执行成功时调用resolve函数返回结果,反之调用reject
  • Promise对象的then方法用来接收处理成功时响应的数据,catch方法用来接收处理失败时相应的数据。

案例1

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script>
        function sayHi() {
            var promise = new Promise(function (resolve, reject) {
                var data = "hello world"
            })
            //将promise对象返回
            //也可以直接return new Promise(function(){})
            return promise
        }

        var p = sayHi()
        console.log(p)

    </script>

</head>
<body>

</body>
</html>

浏览器查看
p是个Promise对象,状态是pending状态。这是由于new Promise里面的函数参数resolve,reject方法都没执行。promise的状态就是pending
在这里插入图片描述

//返回的promise对象的then方法,里面的参数也是个函数。用来处理成功时的响应数据,catch用来处理失败时的响应数据
在这里插入图片描述

我们看到,new Promise里面的函数执行了,但是外面promise对象调用的then函数没有执行
在这里插入图片描述

这是因为,要执行then函数,需要new Promise里面执行函数的参数resolve方法

(3)then函数

Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数**。**
Promise实例具有then方法,也就是说,then方法是定义在原型对象Promise.prototype上的。它的作用是为 Promise 实例添加状态改变时的回调函数。
前面说过,then方法的第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数,它们都是可选的。

then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。

.then(function (){}, function (){});

如果初始函数里面没有指定resolve或者reject函数,那么 .then 函数是不会被调用的,因为之后状态变成了resolved或者rejected才会调用对应的回调函数。

放开resolve方法
在这里插入图片描述

then方法就执行了
在这里插入图片描述

并且,执行了resolve方法
promise的状态也变成了fulfilled
在这里插入图片描述
在这里插入图片描述

此时promiseResult为空
在这里插入图片描述

这是由于我们没把数据传递给resolve

当我们把数据传递给resolve
在这里插入图片描述

promiseResult就有值了
在这里插入图片描述

响应回来的值可以在then方法中,通过then里面函数的参数得到响应值
在这里插入图片描述

在这里插入图片描述

如果没有执行resolve或reject函数,p.then()永远也不会执行
在这里插入图片描述

如果上面的resolve方法没执行,但是reject方法执行了
此时promise的状态是rejected
并且会执行then里面的第二个函数,如果没有第二个函数,程序会报错
在这里插入图片描述
在这里插入图片描述

如果我们把then里面添加了第二个函数,程序会执行第二个函数
在这里插入图片描述
在这里插入图片描述

如果我们把resolve和reject都放开,程序按照从上往下执行,promise的状态只会改变一次
这是因为状态只会改变一次,之后不会更改的
在这里插入图片描述

reject在上面,所以只执行了reject的回调函数
在这里插入图片描述
在这里插入图片描述

promise执行流程:

  1. 构造函数中的输出执行是同步的,输出 apple,执行 resolve 函数,将 Promise 对象状态置为resolved,输出APPLE。
  2. 注册这个Promise对象的回调then函数。
  3. 宏任务继续,打印cherry,整个脚本执行完,stack 清空。
  4. eventloop 检查到 stack为空,再检查 microtask队列中是否有任务,发现了 Promise 对象的 then 回调函数产生的 microtask,推入stack,执行。输出apple banana,eventloop的列队为空,stack为空,脚本执行完毕。

(4)Promise链式应用

使用Promise可以更好地处理异步操作,例如网络请求,文件读取等。它避免了回调地狱(callback hell)的问题,使得代码更加容易理解和维护。
then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。
在这里插入图片描述

案例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script>
        // 第一层:获取用户信息
        function getUserInfo(userId) {
            return new Promise((resolve, reject) => {
                // 模拟异步操作,获取用户信息
                setTimeout(() => {
                    const userInfo = {
                        id: userId,
                        name: "Jing hao",
                        email: "313572372@qq.com"
                    };
                    resolve(userInfo);
                }, 1000);
            });
        }

        // 第二层:获取用户订单列表
        function getUserOrders(userId) {
            return new Promise((resolve, reject) => {
                // 模拟异步操作,获取用户订单列表
                setTimeout(() => {
                    const orders = [
                        {id: 1, product: "Product A"},
                        {id: 2, product: "Product B"},
                        {id: 3, product: "Product C"}
                    ];
                    resolve(orders);
                }, 2000);
            });
        }

        // 第三层:获取订单详情
        function getOrderDetails(orderId) {
            return new Promise((resolve, reject) => {
                // 模拟异步操作,获取订单详情
                setTimeout(() => {
                    const orderDetails = {
                        id: orderId,
                        status: "Delivered",
                        address: "123 Main St"
                    };
                    resolve(orderDetails);
                }, 1500);
            });
        }


        // 应用示例
        const userId = 123;

        //可以连续then,响应成功继续下一步操作
        getUserInfo(userId)
            .then(userInfo => {
                console.log("User Info:", userInfo);
                return getUserOrders(userInfo.id);   //每个then里面返回新的promise函数。如果我们没有手动返回,也会返回的默认的新的Promise对象,其中Promisestate是fulfilled,PromiseResult是undefined
如下,p2的then里面没有写返回值,默认then函数会返回一个新的promise

在这里插入图片描述

            })
            .then(orders => {
                console.log("User Orders:", orders);
                const orderId = orders[0].id;
                return getOrderDetails(orderId);    //每个then里面返回新的promise函数
            })
            .then(orderDetails => {
                console.log("Order Details:", orderDetails);
            })
            //响应失败的数据交给catch
            .catch(error => {
                console.error("Error:", error);
            });

        console.log("后续操作!!!")


    </script>

</head>
<body>

</body>
</html>

在这里插入图片描述

简洁案例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <script>


        function A() {
            var p = new Promise(function (resolve, reject) {

                setTimeout(function () {
                    console.log("A请求")
                    var res = "A-data"
                    resolve(res)
                }, 1000)
            })
            return p
        }


        function B() {
            return new Promise(function (resolve, reject) {
                setTimeout(function () {
                    console.log("B请求")
                    var res = "B-data"
                    resolve(res)
                }, 2000)
            })
        }

        function C() {
            return new Promise(function (resolve, reject) {
                setTimeout(function () {
                    console.log("C请求")
                    var res = "C-data"
                    resolve(res)
                }, 3000)
            })
        }

        function D() {
            return new Promise(function (resolve, reject) {
                setTimeout(function () {
                    console.log("D请求")
                    var res = "D-data"
                    resolve(res)
                }, 3000)
            })
        }

        function E() {
            return new Promise(function (resolve, reject) {
                setTimeout(function () {
                    console.log("E请求")
                    var res = "E-data"
                    resolve(res)
                }, 3000)
            })
        }


        /*var p1 = A()

        var p2 = p1.then(function (res) {
            console.log("A获取结果:", res)
            return B()
        })

        var p3 = p2.then(function (res) {
            console.log("B获取结果:", res)
            return C()
        })

        p3.then(function (res) {
            console.log("C获取结果:", res)

        })*/

       //链式操作
        A().then(function (res) {
            console.log("A获取结果:", res)
            return B()
        }).then(function (res) {
            console.log("B获取结果:", res)
            return C()
        }).then(function (res) {
            console.log("C获取结果:", res)
            return D()
        }).then(function (res) {
            console.log("D获取结果:", res)
            return E()
        }).then(function (res) {
            console.log("E获取结果:", res)
        })


    </script>
</head>
<body>


</body>
</html>

通过resolve或reject将响应结果返回,拿到外面管理,就避免了地狱回调的出现

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

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

相关文章

鸿蒙开发:从入门到精通的全方位学习指南

随着华为鸿蒙HarmonyOS生态系统的迅速扩展&#xff0c;越来越多的开发者渴望深入了解并掌握这一前沿技术。本文旨在为鸿蒙开发新手提供一份详尽且实用的学习教程&#xff0c;助您从零开始&#xff0c;逐步迈向鸿蒙开发的巅峰。 一、鸿蒙开发环境搭建 DevEco Studio安装&#x…

12---风扇电路设计

视频链接 风扇硬件电路设计01_哔哩哔哩_bilibili 风扇电路设计 1、风扇简介 电脑风扇又称为散热风扇&#xff0c;一般用于散热。提供给散热器和机箱使用。市面上一般的散热风扇尺寸大小由直径2.5cm到30cm都有&#xff0c;厚度由6mm到76mm都有&#xff0c;而根据不同运作要求…

美摄科技对抗网络数字人解决方案

在数字化浪潮的推动下&#xff0c;企业对于高效、创新且具备高度真实感的数字化解决方案的需求日益迫切。美摄科技凭借其在人工智能和计算机视觉领域的深厚积累&#xff0c;推出了一款全新的对抗网络数字人解决方案&#xff0c;该方案能够为企业构建出表情和动作都极为逼真的数…

ssm+vue的高校课程评价系统(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频&#xff1a; ssmvue的高校课程评价系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&…

SSL---VPN

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 一.SSL-VPN概述 SLL VPN是一种基于HTTPS&#xff08;即支持SSL的HTTP协议&#xff09;的远程安全接入技术。它充分利用了SSL协议提供的基于证书的身份认证、数据加密和消息完整性验证机制&#…

2024.3.10 C++

提示并输入一个字符串&#xff0c;统计该字符中大写、小写字母个数、数字个数、空格个数以及其他字符个数要求使用C风格字符串完成 #include <iostream>using namespace std;int main() {char str[20];cout << "please enter the str:";gets(str);int u…

sqli-labs练习

2关 找出数据库名字 从数据库security 中找到表明名: 找到数据库名字: 从表users中找到列: 取出表users用户名和密码:用户名~密码 3关 判断出id是(‘id’)的形式 4关 双引号测试报错,推测是(“id“) 5关 填写id=1没有回显信息(布尔盲注一般适用于页面没有回显字…

connection SQLException, url:jdbc ,errorCode 0, state 08S01

connection SQLException, url: jdbc:mysql://localhost:3306/itcast_health?useUnicodetrue&characterEncodingutf-8, errorCode 0, state 08S01 添加&#xff1a;&useSSLfalse 添加前 添加后&#xff1a; 查询数据库正常

2.1 关系数据结构及形式化定义 数据库概论

目录 2.1.1 关系 关系&#xff1a;概念 1. 域&#xff08;Domain&#xff09; 2.笛卡尔积 元组&#xff08;Tuple&#xff09; 分量&#xff08;Component&#xff09; 基数&#xff08;Cardinal number&#xff09; 3. 关系 候选码&#xff08;Candidate key&#xf…

Docker 快速入门实操教程ER(完结)

Docker 快速入门实操教程&#xff08;完结&#xff09; 如果安装好Docker不知道怎么使用&#xff0c;不理解各个名词的概念&#xff0c;不太了解各个功能的用途&#xff0c;这篇文章应该会对你有帮助。 前置条件&#xff1a;已经安装Docker并且Docker成功启动。 实操内容&…

Leetcode 675 为高尔夫比赛砍树

文章目录 1. 题目描述2. 我的尝试3. 题解1. BFS 1. 题目描述 Leetcode 675 为高尔夫比赛砍树 2. 我的尝试 typedef priority_queue<int, vector<int>, greater<int>> heap;class Solution { public:int m;int n;int bfs(vector<vector<int>>&…

【力扣hot100】刷题笔记Day25

前言 这几天搞工作处理数据真是类似我也&#xff0c;还被老板打电话push压力有点大的&#xff0c;还好搞的差不多了&#xff0c;明天再汇报&#xff0c;赶紧偷闲再刷几道题&#xff08;可恶&#xff0c;被打破连更记录了&#xff09;这几天刷的是动态规划&#xff0c;由于很成…

二分查找刷题(二)

目录 1.搜索插入位置 算法原理 代码编写 2.x 的平方根 算法原理 代码编写 3.山脉数组的峰顶索引 算法原理 1.搜索插入位置 算法原理 判断二段性 可以将区间分于5和大于等于5的两个区间&#xff0c;可以使用二分查找搜索左区间的模板。 代码编写 int searchInsert(vect…

【触想智能】工业触摸显示器在户外使用需要注意哪些问题?

工业显示器是智能制造领域应用比较广泛的电子产品&#xff0c;它广泛应用于工厂产线以及各种配套设备&#xff0c;在很大程度上提升了工厂的生产效率。 工业显示器按触摸方式分&#xff0c;可以分为工业触摸显示器和非触摸工业显示器两种;按使用环境分&#xff0c;又可以分为室…

计算机网络面经八股-什么是 SYN洪泛攻击?如何防范?

SYN洪泛攻击属于 DOS 攻击的一种&#xff0c;它利用 TCP 协议缺陷&#xff0c;通过发送大量的半连接请求&#xff0c;耗费 CPU 和内存资源。 原理&#xff1a; 在三次握手过程中&#xff0c;服务器发送 [SYN/ACK] 包&#xff08;第二个包&#xff09;之后、收到客户端的 [ACK…

Go语言框架路由Controller控制器设计思路gin路由根据控制器目录分层生成路由地址

Controller设计好处 框架设计用controller分请求路由层级&#xff0c;应用从app目录开始对应请求url路由地址&#xff0c;这样设计师方便开发时候通过请求地址层级快速定位接口方法对应的代码位置。 例如api接口请求路径为&#xff1a;​​http://localhost:8110/​​busines…

解码人工智能的幽默:理解其背后的误解与挑战

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

码垛机夹具设计:材料选择与应用考量

在现代工业生产中&#xff0c;码垛机夹具扮演着至关重要的角色。作为连接产品与搬运设备的桥梁&#xff0c;夹具的设计直接影响到生产效率和产品质量。本文将深入探讨码垛机夹具的基本原理及设计要素。 码垛机夹具的工作原理基于对产品的抓取和释放。这一过程看似简单&#xf…

玩转LangChain - 2 在本地跑Google新出的Gemma模型

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

海格里斯HEGERLS智能托盘四向车系统为物流仓储自动化升级提供新答案

随着实体企业面临需求多样化、订单履行实时化、商业模式加速迭代等挑战&#xff0c;客户对物流仓储解决方案的需求也逐渐趋向于柔性化、智能化。作为近十年来发展起来的新型智能仓储设备&#xff0c;四向车系统正是弥补了先前托盘搬运领域柔性解决方案的空白。随着小车本体设计…