回调地狱及解决回调地狱的终极目标

目录

一、回调地狱的定义

二、解决回调地狱的终极目标

三、promise语法

3.1  定义

3.2  封装promise函数

 3.3  语法形式

四、async 和 await语法

4.1  定义

4.2  封装async函数

4.3  语法形式


一、回调地狱的定义

 所谓的回调地狱 就是在 回调函数中 继续调用执行新的回调函数,本质就是回调函数的嵌套使用。

如:

 myAjax( 地址 , 方式 , 参数 , function( response1 ){

                    根据 第一次的请求结果 再次 发起 第二次请求

                    myAjax( 地址 , 方式 , 参数 , function( response2 ){

                        根据 第二次的请求结果 再次 发起 第三次请求

                        myAjax( 地址 , 方式 , 参数 , function( response3){

                            根据 第三次的请求结果 执行对应的程序

                        })

                    })

                })

这就是回调函数的嵌套使用。 

二、解决回调地狱的终极目标

将嵌套的语法形式写成并列的语法形式。

myAjax( 地址 , 方式 , 参数 , function( response1 ){})

myAjax( 地址 , 方式 , 参数 , function( response2 ){})

myAjax( 地址 , 方式 , 参数 , function( response3 ){})

但是,Ajax请求是异步程序,如果使用并且的语法会同时开始执行,需要通过JavaScript语法操作让回调函数既写成并列的语法形式又按照顺序一个一个执行。 

三、promise语法

3.1  定义

将promise封装成一个函数,函数的return返回值是promise对象,通过 返回值 定义 .then 和 .catch。

3.2  封装promise函数

function 函数( 异步程序需要的参数 ){

    const p = new Promise(function(参数1,参数2){

        异步程序的执行

        执行成功  参数1( 实参 );

        执行鼠标  参数2( 实参 );

    })

    return p ;

}

代码展示:

// 封装一个promise程序执行 ajax请求
// 参数1    请求的url地址
// 参数2    请求的方式 
// 参数3    携带的参数怇
function myPromiseAjax( url , type = 'get' , data = '' ){
    // 创建一个 promise 对象 
    const p = new Promise(function( fulfilled , rejected ){
        // 执行异步ajax请求
        const xhr = new XMLHttpRequest() ;

        if( type.toLowerCase() === 'get' ){
            // get请求方式
            xhr.open( 'get' , `${url}?${data}` );
            xhr.send();

        }else{
            // post请求方式
            xhr.open( 'post' , url );
            xhr.setRequestHeader('Content-Type' , 'application/x-www-form-urlencoded');
            xhr.send(data);
        }

        // 接收 请求结果
        xhr.onreadystatechange = function(){  
            // 当 ajax状态码是 4 时 判断 http状态码          
            if( xhr.readyState === 4 ) {

                // 如果 http状态码 是 200 - 299 
                if( /^2\d{2}$/.test( xhr.status ) ){
                    // 请求成功
                    fulfilled( xhr.response );  

                }else if( /^(4|5)\d{2}$/.test( xhr.status )  ){
                    // 请求失败
                    rejected( xhr.statusText );

                }
            }
        }

    });

    // return 返回这个promise对象
    return p;
}

 3.3  语法形式

第一次

const 变量 = 函数( 异步程序需要的实参 );

变量.then( function( 参数 ){

    第一次执行成功对应的函数程序

    第二次

    return 函数( 异步程序需要的实参 );

})

.then( function( 参数 ){

    第二次执行成功对应的函数程序

    第三次

    return 函数( 异步程序需要的实参 );

})

.then( function(){

    第三次执行成功对应的函数程序

})

promise的本质 并不能真的将异步程序写成并列的语法形式 并且按照顺序执行, 本质上 异步程序还是 嵌套的语法形式,只是 通过 .then .catch 将 回调函数 定义在 异步请求之外设定,效果是 看上去 好像是 一个一个执行程序。

代码展示:

 <button>请求</button>

    <script src="../../../ajax.js"></script>
    <script>
        // 点击发起请求
        const oBtn = document.querySelector('button');

        oBtn.addEventListener( 'click' , function(){
            // 第一次调用 函数 执行生成 promise对象
            // p1 存储的是 第一次请求 生成的 promise实例化对象
            const p1 = myPromiseAjax( 'http://localhost:8888/users/register' , 'post' , 'username=123456000&password=123456&rpassword=123456&nickname=123456' );
        
            // 通过 实例化对象.then 定义 请求成功的回调函数
            p1.then( function( response1 ){

                response1 = JSON.parse( response1 )
                console.log( response1 );

                // 第二次请求 直接 return 新的请求
                return myPromiseAjax( 'http://localhost:8888/users/login' , 'post' , 'username=123456000&password=123456' );

            })
            // p1.then() 执行结果 就是 一个新的 promise对象也就是 p2
            // 可以 写 p1.then().then()
            .then(function( response2 ){

                response2 = JSON.parse( response2 )
                console.log( response2 );
            
                return myPromiseAjax( 'http://localhost:8888/users/logout' , 'get' , `id=${response2.user.id}`);

            })
            // p1.then().then() 执行结果 又是一个新的promise对象 也就是 p3
            // 可以写  p1.then().then().then()
            .then( function( response3 ){
                response3 = JSON.parse( response3 )
                console.log( response3 );
            })

            // 通过 实例化对象.catch 定义 请求失败的回调函数
            p1.catch();
        })


    </script>

运行结果;

这里用的是老师自己搭建的本地服务器,仅用于教学使用。

四、async 和 await语法

4.1  定义

async 和 await是ES7新增的语法规范,配合promise封装函数执行程序。

4.2  封装async函数

在 async定义的函数中 使用 await 调用 封装的promise函数,执行结果 不再是 return的 promise实例化对象,执行结果 是 异步请求的 响应体数据,以直接定义 下一个 异步请求,await 会 按照顺组一个一个的执行。

代码展示:

// 使用 async 定义封装一个函数
        async function getAjax(){
            // 使用 await 调用 promise封装的函数
            // await 获取的是 异步请求 执行的 响应体结果 不再是 promise对象
            // 不再需要 执行 promise对象.then() 执行成功触发的函数程序 
            // 可以直接写下一次调用
            const response1 = JSON.parse( await myPromiseAjax( 'http://localhost:8888/users/register' , 'post' , 'username=123456bbb&password=123456&rpassword=123456&nickname=123456' ) );
            console.log( response1 );

            // 可以直接定义第二次请求 await 会按照顺序执行程序代码
            const response2 = JSON.parse( await myPromiseAjax( 'http://localhost:8888/users/login' , 'post' , 'username=123456bbb&password=123456' ) );
            console.log( response2 );

            // 可以直接定义第三次请求 await 会按照顺序执行程序代码
            const response3 = JSON.parse( await myPromiseAjax( 'http://localhost:8888/users/logout' , 'get' , `id=${response2.user.id}` ) );
            console.log( response3 );
        
        }

4.3  语法形式

async function 函数(){

                第一次调用

                const 变量1 = await promise封装函数() ;

                    变量1 存储的是 ajax请求的响应体结果

                    不再是 promise实例化对象

                第二次调用

                直接调用 不需要在使用 promise对象.then()

                await 会按照顺序执行 一个一个的 异步程序

                const 变量2 = await promise封装函数() ;

                第三次调用

                const 变量3 = await promise封装函数() ;

            }

代码展示:

  <button>请求</button>

    <script src="../../../ajax.js"></script>
    <script>
        const oBtn =document.querySelector('button');
        oBtn.addEventListener('click' , function(){
            // 调用执行 async 封装的函数
            getAjax() ;
        })

        // 使用 async 定义封装一个函数
        async function getAjax(){
            // 使用 await 调用 promise封装的函数
            // await 获取的是 异步请求 执行的 响应体结果 不再是 promise对象
            // 不再需要 执行 promise对象.then() 执行成功触发的函数程序 
            // 可以直接写下一次调用
            const response1 = JSON.parse( await myPromiseAjax( 'http://localhost:8888/users/register' , 'post' , 'username=123456bbb&password=123456&rpassword=123456&nickname=123456' ) );
            console.log( response1 );

            // 可以直接定义第二次请求 await 会按照顺序执行程序代码
            const response2 = JSON.parse( await myPromiseAjax( 'http://localhost:8888/users/login' , 'post' , 'username=123456bbb&password=123456' ) );
            console.log( response2 );

            // 可以直接定义第三次请求 await 会按照顺序执行程序代码
            const response3 = JSON.parse( await myPromiseAjax( 'http://localhost:8888/users/logout' , 'get' , `id=${response2.user.id}` ) );
            console.log( response3 );
        
        }

运行结果:

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

大聪明码农徐

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

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

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

打赏作者

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

抵扣说明:

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

余额充值