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

html 复制代码
<!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

html 复制代码
<!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方法。

案例:

html 复制代码
<!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
html 复制代码
            })
            .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>

简洁案例:

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将响应结果返回,拿到外面管理,就避免了地狱回调的出现

相关推荐
刚刚好ā15 分钟前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
yqcoder2 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
会发光的猪。2 小时前
css使用弹性盒,让每个子元素平均等分父元素的4/1大小
前端·javascript·vue.js
天下代码客3 小时前
【vue】vue中.sync修饰符如何使用--详细代码对比
前端·javascript·vue.js
Domain-zhuo3 小时前
什么是JavaScript原型链?
开发语言·前端·javascript·jvm·ecmascript·原型模式
小丁爱养花3 小时前
前端三剑客(三):JavaScript
开发语言·前端·javascript
码农六六4 小时前
vue3封装Element Plus table表格组件
javascript·vue.js·elementui
徐同保4 小时前
el-table 多选改成单选
javascript·vue.js·elementui
快乐小土豆~~4 小时前
el-input绑定点击回车事件意外触发页面刷新
javascript·vue.js·elementui
建群新人小猿5 小时前
会员等级经验问题
android·开发语言·前端·javascript·php