鹤林玉露
罗大经

一愿识尽世间好人

二愿读尽世间好书

三愿看尽世间好山水

Promise也是ES6的新特性。

基本介绍

传统的 Ajax 异步调用在需要多个操作的时候,会导致多个回调函数嵌套,导致代码不够直观。为了解决传统的回调嵌套的问题,我们出现了Promise。Promise 是异步编程的一种解决方案。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。

使用

演示需要用到的json文件

monster.json
{
  "id" : 1,
  "name" : "黑山老妖"
}
monster_detail_1.json
{
  "id" : 1,
  "address" : "黑山洞",
  "skill" : "无法无天",
  "age" : 500,
  "gfid" : 2
}

使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>jquery_ajax多次请求</title>
    <script type="text/javascript" src="script/jquery-3.6.0.min.js"></script>
    <script type="text/javascript">
        // jquery发出ajax请求
        $.ajax({
            url: "data/monster.json",
            success: function (resultData) {
                console.log("第一次ajax请求 monster基本信息",resultData);
                // 发出第二次ajax请求
                $.ajax({
                    url: `data/monster_detail_${resultData.id}.json`,
                    success: function (resultData) {
                        console.log("第二次ajx请求,monster详细信息",resultData);
                    },
                    error: function (err) {
                        console.log("出现异常",err)
                    }
                })

            },
            error: function (err) {
                console.log("出现异常= ",err);
            }
        })

    </script>
</head>
<body>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>使用promise完成多次ajax请求</title>
    <script type="text/javascript" src="script/jquery-3.6.0.min.js"></script>
    <script type="text/javascript">
        // 先请求到monster.json
        /**
         * 创建Promise对象
         * 构造函数传入一个箭头函数
         * (resolve,reject)参数猎豹resolve:如果请求成功,调用resolve函数
         * 如果请求失败,调用reject函数
         * 箭头函数体,仍然是通过jquery发送ajax
         * @type {Promise<unknown>}
         */
        let p = new Promise((resolve,reject)=>{
            // 发出ajax
            $.ajax({
                url : "data/monster.json",
                success: function (resultData) {// 成功的回调函数
                    console.log("promise发出的第一次ajax monster基本信息=",resultData)
                    resolve(resultData);
                },
                error: function (err) {
                    // console.log("promise1发出的异步请求异常=",err);
                    reject(err);
                }
            })
        })

        // 这里我们可以继续编写请求成功后的业务
        p.then((resultData)=>{
            // 这里我们可以继续发出请求
            // console.log("p.then 得到resultData=",resultData);
            return new Promise((resolve,reject)=>{
                $.ajax({ //第二次ajax请求成功,回到函数
                    url: `data/monster_detail_${resultData.id}.json`,
                    success: function (resultData) {
                        console.log("第二次ajax请求 monster的详细信息=",resultData);
                    },
                    error: function (err) { //第二次请求失败,回调函数
                        // console.log("promise2发出的异步请求异常=",err);
                        reject(err);
                    }
                })
            })
        })).then((resultData) => {

            console.log("p.then().then(), resultData", resultData)
            //即可以在这里发出第 3 次 ajax 请求=》 获取该妖怪的女友
            return new Promise((resolve, reject) => {
            $.ajax({
            url: `data/monster_gf_${resultData.gfid}.json`, 
            success(resultData) { //第 3 次 ajax 请求成功,回调函数
            console.log("第 3 次 ajax 请求 monster 女友的详细信息=", 
            resultData);
        	//reject(err);
            		}
            	})
            })
		}).catch((err)=>{
            console.log("promise异步请求异常=",err);
        })
    </script>
</head>
<body>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>promise代码重排</title>
    <script type="text/javascript" src="script/jquery-3.6.0.min.js"></script>
    <script type="text/javascript">
        /**
         * 这里我们讲重复的代码抽取出来,编写一个get方法
         * @param url ajax请求地址
         * @param data 携带的数据
         * @returns {Promise<unknown>}
         */
        function get(url,data) {
            return new Promise((resolve,reject)=>{
                $.ajax({
                    url:url,
                    data: data,
                    success(resultData){
                        resolve(resultData);
                    },
                    error(err){
                        reject(err);
                    }
                })
            })
        }

        // 需求:完成
        //1. 先获取monster.json
        //2. 获取monster_detail_1.json
        //3. 获取monster_gf_2.json
        get("data/monster.json")
            .then((resultData)=>{
                //第一次ajax请求成功后的处理代码
                console.log("第一次",resultData);
                return get(`data/monster_detail_${resultData.id}.json`);
        }).then((resultData)=>{
            //第二次ajax请求成功后的处理代码
            console.log("第二次ajax请求成功后的处理代码",resultData);
            return get(`data/monster_gf_${resultData.gfid}.json`);
        }).then((resultData)=>{
            //第三次ajax请求成功后的处理代码
            console.log("第三次ajax请求成功后的处理代码",resultData);
            // return get(`data/monster_gf_${resultData.gfid}.json`);
        }).catch((err) => {
            console.log("promise请求异常",err);
        })
    </script>
</head>
<body>
</body>
</html>

注意事项

  1. 如果返回的是 Promise 对象,可以继续执行.then()
  2. then((data)=>{}) 的 data 数据是上一次正确执行后 resolve(data) 返回传入的
  3. 通过多级.then() 可以对异步请求分层次请求,实现代码重排,代码逻辑更加清晰合理
  4. 通过多级.then() 后面的 .catch((err) => {}) 可捕获发生异常,便于调试