JS-11-es6常用知识-Promise(6K字超级详解!!)

文章目录

1 回调地狱

2 Promise函数基本用法

3 Promise函数实现多层回调

 4 Promise传参

5 Promise 错误处理

5.1 两种错误处理方式

5.2 catch捕获错误

5.3 多层异步种使用catch

6 使用 Promise 的优势


1 回调地狱

1)为什么要有promise?

   解决(回调地狱)的问题 

2)什么是回调?

    回调(Callback)是一种编程模式,其中一段可执行的代码(即回调函数)作为参数传递给另一个函数(即主函数),并在需要时由主函数执行。这种机制允许主函数在特定事件或条件满足时,调用并执行之前注册的回调函数。

function greet(name, callback) {  
  console.log(`Hello, ${name}!`);  
  callback(); // 调用回调函数  
}  
  
function sayGoodbye() {  
  console.log('Goodbye!');  
}  
  
greet('Alice', sayGoodbye); // 输出 "Hello, Alice!" 和 "Goodbye!"

     在这个示例中,greet函数接受一个name参数和一个callback回调函数作为参数。当greet函数被调用时,它会先输出一条问候语,然后调用callback回调函数。在这个例子中,sayGoodbye函数被作为回调函数传递给greet函数,并在greet函数内部被调用。

3)什么是回调地狱?

    回调地狱(Callback Hell)是指在编写异步JavaScript代码时,回调函数嵌套的现象越来越深,导致代码的可读性变差、维护性变差、复杂度增加、错误率增加等问题。回调地狱通常表现为深度嵌套并且难以阅读的代码,例如:

    //跟以前的if条件地狱很像
    // if(){
    //     if(){
    //         if(){
    //         }
    //     }
    // }

    $.get("/getUser",function(res){
        $.get("/getUserDetail",function(){
            $.get("/getCart",function(){
                $.get("/getBooks",function(){
                    //...
                })
            })
        })
    })

    //node开发:读取文件;开个服务器、接收一个请求、请求路径、访问数据库

2 Promise函数基本用法

     例1:下面代码是一个使用 Promise 来封装异步操作(在这个例子中是使用 jQuery 的 $.get 方法来发送一个 GET 请求到 "/getUser")的例子:执行顺序:abcd

    var promise=new Promise((resolve,reject)=>{
        //b 把需要执行的异步操作放在这里
        $.get("/getUser",res=>{
            //获取数据的异步操作已经执行完毕了,等待下一步的执行,通过执行resolve函数,告诉外界你可以执行下一步操作了
            //c、
            resolve(res)
            //而执行的下一步操作,其实就是写在then的回调函数中的
        })
    })
    //a、
    promise.then(res=>{
        //d、执行后续的操作
        console.log(res);
    })

1)创建 Promise

var promise = new Promise((resolve, reject) => {  
    // ...  
});

      这里,创建了一个Promise 实例。Promise 是一个对象,它代表一个最终可能完成(也可能被拒绝)的异步操作及其结果值。Promise 构造函数接受一个执行器函数,这个函数有两个参数:resolve 和 reject。这两个函数都是用于改变 Promise 状态的。

2)执行异步操作

$.get("/getUser", res => {  
    // ...  
    resolve(res);  
});

      在 Promise 的执行器函数内部,使用 jQuery 的 $.get 方法发送了一个 GET 请求到 "/getUser"。当请求成功时,jQuery 会调用提供的回调函数,并传入响应数据 res。在这个回调函数中,调用了 resolve 函数,并将响应数据 res 作为参数传递给它。这表示异步操作已经成功完成,并且这里有一个结果值要返回给 Promise 的调用者。

3)处理 Promise 的结果

promise.then(res => {  
    // ...  
    console.log(res);  
});

  使用 promise.then() 方法,你指定了一个回调函数来处理 Promise 的结果。当 Promise 的状态变为 "fulfilled"(即 resolve 函数被调用)时,这个回调函数会被执行,并且 resolve 函数的参数(在这个例子中是 res)会被作为回调函数的参数。在这个例子中,回调函数只是简单地打印了响应数据 res 到控制台。

     例2:读代码,感受promise的基本用法

<script>
    //把异步操作封装在一个promise对象中
    function fn(){
        return new Promise((resolve,reject)=>{
            setTimeout(()=>{
                console.log('你好');

                //其实异步逻辑到这里其实已经执行完毕了,
                //就可以告诉外界,可以执行其他操作了
                //如何告诉外界,让外界得知?
                resolve();
            },1000);
        })
    }
    //调用了这个函数,执行了异步操作
    //fn()
    //存在问题,并不知道这个异步操作什么时候结束
    fn().then(res=>{
        //执行到下一步
        console.log("下一步");

        fn().then(res=>{
            console.log("执行第二步");
        })
    })

    //输出顺序:
    //你好
    //下一步
    //你好
    //执行第二步

</script>

3 Promise函数实现多层回调

-解决回调地狱

    例1:-> 获取用户 -> 获取用户基本信息 -> 查看用户详情 -> 查看购物车信息

    new Promise((resolve,reject)=>{
        $.get("/getUser",res=>{
            resolve(res)
        })
    }).then(res=>{
        //用户基本信息
        return new Promise(resolve=>{
            $.get("/getUserDetail",res=>{
                resolve(res)
            })
        })
    }).then(res=>{
        //用户详情
        return new Promise(resolve=>{
            $.get("/getCart",res=>{
                resolve(res)
            })
        })
    }).then(res=>{
        //购物车信息
    })

  例2:第一步 -> 第二步 -> 第一步 -> 第二步 -> 完成

<script>
    function f1(){
        return new Promise(resolve=>{
            setTimeout(()=>{
                console.log('第一步');
                
                //异步逻辑已经执行完,必须要告诉外界我执行完了
                resolve();

            },1000)
        })
    }
    function f2(){
        return new Promise(resolve=>{
            setTimeout(()=>{
                console.log('第二步');
                
                //告诉外界我执行完了
                resolve();
            },1000)
        })
    }

    f1().then(res=>{
        //返回一个promise对象
        return f2();
    }).then(res=>{
        return f1();
    }).then(res=>{
        return f2();
    }).then(res=>{
        setTimeout(()=>{
            console.log('完成');
        },1000)
    })

</script>

 4 Promise传参

    function getUser(){
        return new Promise(resolve=>{
            $.get("/getUser",res=>{
                //res是从服务器中接收到的数据
                //把数据传到下一步操作中
                //告诉外界本次的异步操作已经执行完毕了
                resolve(res)
            })
        })
    }
    getUser().then(res=>{
        //res就表示上一个异步操作返回的参数值:从服务器中获取的数据
    })

Promise 错误处理

5.1 两种错误处理方式

 第一种方式,then里包含成功、失败两个返回值

new Promise((resolve,reject)=>{
        $.ajax({
            url:"/getUser",
            type:"GET",
            success:res=>{
                resolve(res);
            },
            error:res=>{
                reject(res)
            }
        })
    }).then(resSuccess=>{
        //成功的返回值
    },resError=>{
        //失败的返回值
    })

第二种方式:catch(推荐)

new Promise((resolve,reject)=>{
        $.ajax({
            url:"/getUser",
            type:"GET",
            success:res=>{
                resolve(res);
            },
            error:res=>{
                reject(res)
            }
        })
    }).then(resSuccess=>{
        //成功的返回值
    }).catch(resError=>{
        //失败的返回值
    })

小结:上面2种错误处理的方式,第二种更加推荐。第二种方式更强大的地方在于:

    a、不仅仅可以捕获到reject传递的参数

    b、还可以捕获到:成功的回调中发生的错误

样例:

<script>
    function getBooks(){
        //执行了resolve()表示异步操作是成功的
        //执行了reject()表示异步操作是失败的
        return new Promise((resolve,reject)=>{
            $.ajax({
                url:"/getBooks",
                success(res){
                    //成功获取数据
                    resolve(res);       
                },
                error(resError){     //res表示错误信息
                    //如果失败,执行error方法
                    
                    //通过执行reject函数,把错误信息传递给外界
                    reject(resError)
                }
            })
        })
    }

    //第一种处理错误的方式:
    // getBooks().then(res=>{
    //     //res表示请求成功时候获取到的数据
    // },resError=>{
    //     console.log(resError);
    // })

    //第二种错误处理的方式:
    // getBooks().then(res=>{
    //     //成功了
    // }).catch(resError=>{
    //     //这里也可以获取到错误信息
    // })

</script>

5.2 catch捕获错误

      catch不仅能捕获错误信息,还能捕获到成功后的代码错误信息

setTimeout 来模拟异步操作。这个异步操作将在 1 秒(1000 毫秒)后完成

     function f1(name){
        return new Promise((resolve,reject)=>{
            setTimeout(()=>{
                if(name=="a"){
                    resolve("成功");
                }else{
                    reject("失败")
                }
            },1000)
        })
    }

then里处理

    f1("b").then(res=>{
        console.log('成功了');
    },resError=>{
        console.log('失败了');
    })

catch处理

  f1("b").then(res=>{
        console.log('成功了');
    }).catch(res=>{
        console.log('失败了');
    })

catch处理成功信息里出现代码错误

    f1("a").then(res => {
        var a = 5;
        a();        //这里代码发生了错误    
    }).catch(res => {
        //成功的捕捉到了成功回调中的代码错误
        console.log(res);
    })

效果(打印错误,控制台没出现红色报错信息)

5.3 多层异步种使用catch

    例1:首先执行第一步-> 成功-> 第二步-> 失败-> 

    new Promise((resolve,reject)=>{
        setTimeout(()=>{
            console.log('第一步');
            resolve("第一步完成")
        },100)
    }).then(res=>{
        console.log(res);   //res:第一步完成
        return new Promise((resolve,reject)=>{
            setTimeout(()=>{
                console.log('第二步');
                reject('第二步失败');
            },100)
        })
    }).then(res=>{
        //并不会执行到这里
        console.log('第二步成功');
    }).catch(res=>{
        console.log(res);
    })

效果:

      拓展: axios就是一个基于Promise封装出来的进行ajax请求的库

    axios.get("/getUser").then(res=>{

        return axios.get("/getUserDetail")

    }).get("/getLoginInfo").then(res=>{
        console.log('');
    })

6 使用 Promise 的优势

  1. 代码结构更清晰:Promise 允许我们将异步操作的组织方式从传统的嵌套回调(callback hell)转变为链式调用,这使得代码结构更加清晰,易于理解和维护。

  2. 错误处理更简洁:传统的嵌套回调中,错误处理通常需要在每个回调函数中显式地添加错误处理逻辑。而 Promise 提供了 .catch() 方法,可以一次性捕获多个异步操作中的错误,使错误处理更加简洁和统一。

  3. 支持链式调用:Promise 支持链式调用,可以通过 .then() 方法将多个异步操作串联起来,形成一个执行流程。这使得异步代码更加易于组织和管理,提高了代码的可读性和可维护性。

  4. 更好的可读性和可维护性:Promise 的语法更接近于同步代码,使得异步代码的阅读和编写更加直观。此外,Promise 还支持 ES6 的 async/await 语法,可以将异步代码转换为看起来更像同步代码的形式,进一步提高了代码的可读性和可维护性。

  5. 更好的返回值处理:Promise 的 resolve 方法可以传递任何类型的值(包括其他 Promise),这使得我们可以更加灵活地处理异步操作的返回值。在多层回调中,通常需要手动处理每个回调函数的返回值,而在 Promise 中,我们可以使用 .then() 方法来统一处理返回值。

  6. 可取消的异步操作(虽然 Promise 本身不直接支持取消,但可以通过扩展 Promise 或者使用其他库来实现):在某些情况下,我们可能需要取消正在进行的异步操作。虽然 Promise 本身并不直接支持取消操作,但我们可以通过扩展 Promise 或者使用其他库(如 Bluebird)来实现取消功能。

  7. 更好的组合和复用:Promise 提供了 Promise.all()Promise.race() 等静态方法,允许我们更方便地对多个 Promise 进行组合和复用。这些功能在多层回调中很难实现。

  • 33
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mikuc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值