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 的相关文章