Promise对象详解

  最近我在看一个uniAPP项目的源码,本是无意翻翻看,却偶然看到了这样一段代码

uni.addInterceptor({
  returnValue(res) {
    if(!isPromise(res)) {
      return res;
    }
    return new Promise((resolve, reject) => {
      res.then((res) => {
        if(res[0]) {
          reject(res[0]);
        } else {
          resolve(res[1]);
        }
      });
    });
  },
});
} catch(err) {}

发现我看不懂这段代码的逻辑。然后我去搜索引擎搜了一下。

这段代码大概是这个意思:

该段代码是一个拦截器,用于处理返回值。具体来说,它检查返回值是否为Promise类型,

如果是,就通过Promise处理函数进行处理,并将处理结果返回给调用方。

代码中的`uni`是uniAPP类的一个实例,其`addInterceptor`方法用于添加拦截器。该拦截器有一个名为`returnValue`的处理函数,该函数接收一个参数`res`,用于处理返回值。

如果返回值`res`不是Promise类型,则直接将其返回。如果`res`是Promise类型,则通过Promise处理函数进行处理,并返回处理结果。

具体来说,处理函数首先检查Promise对象是否被成功解析(即是否执行了`resolve`方法)。

如果Promise对象被成功解析,则将解析结果作为处理结果返回。如果Promise对象被拒绝(即执行了`reject`方法),则将拒绝原因作为错误信息抛出(即通过`reject(res[0)`抛出)。

try...catch 块中使用 uni.addInterceptor 可能是因为 addInterceptor 方法可能会抛出错误,为了避免该错误影响程序的正常执行,使用 try...catch 块来捕获可能的错误。

其中Promise是异步编程的一种解决方案。

因为传统的Ajax异步调用在需要多个操作的时候,会导致多个回调函数嵌套,导致代码不够直观,就是常说的Callback Hell

For Example:

 Student.json:

{
    "id":1,
    "name":"诉衷情の麻雀"
}

Student_detail_1.json

{
    "id":1,
    "address":"中国洛阳",
    "age":18
}

 然后我用Ajax发送第一次请求

 <script type="text/javascript">
        //jquery发出ajax的方式
        $.ajax({
            url: "data/Student.json",
            success(resultData) {//如果请求成功了,回调处理函数success
                console.log("第1次ajax请求 Student基本信息=", resultData);
            },
            error(err) {
                console.log("出现异常=", err);
            }
        })

    </script>

 第一次请求成功,那么我再用Ajax发送第二次请求

<script type="text/javascript">
        //jquery发出ajax的方式
        $.ajax({
            url: "data/Student.json",
            success(resultData) {//如果请求成功了,回调处理函数success
                console.log("第1次ajax请求 Student基本信息=", resultData);
                $.ajax({
                    url:`data/Student_detail_${resultData.id}.json`,
                    success(resultData) {
                        console.log("第2次Ajax请求的Student的详细信息",resultData)
                    },error(err) {
                        console.log("出现异常")
                    }
                })
            },
            error(err) {
                console.log("出现异常=", err);
            }
        })

    </script>

 同样我们是拿到student的详细信息了

如果我们要发送第三次、第四次Ajax请求呢?那是不是要在success继续嵌套多个Ajax

所以这种写法代码冗余度较高,不易维护。 

因此Promise就是为了解决这个问题应运而生

下面我将演示用Promise发送Ajax请求

<script type="text/javascript">
      //先请求到Student.json
      //1. 创建Promise对象
      //2. 构造函数传入一个箭头函数
      //3.(resolve, reject)参数列表resolve: 如果请求成功,调用resolve函数
      //4. 如果请求失败,调用reject函数
      //5. 箭头函数体,仍然是通过jQuery发出了Ajax请求
      let p = new Promise((resolve,reject) => {
        //发出Ajax请求
        $.ajax({
            url:"data/Student.json",
            success(resultData) { //成功的回调函数
                console.log("promise发出的一次Ajax Student基本信息:" ,resultData);

            },
            error(err) {
                console.log("promise 发出的异步请求异常: ", err);
            }
        })
      })

    </script>

得出来的结果

 下面我用Promise发出第二次Ajax请求

<script type="text/javascript">
      //先请求到Student.json
      //1. 创建Promise对象
      //2. 构造函数传入一个箭头函数
      //3.(resolve, reject)参数列表resolve: 如果请求成功,调用resolve函数
      //4. 如果请求失败,调用reject函数
      //5. 箭头函数体,仍然是通过jQuery发出了Ajax请求
      let p = new Promise((resolve,reject) => {
        //发出Ajax请求
        $.ajax({
            url:"data/Student.json",
            success(resultData) { //成功的回调函数
                console.log("promise发出的一次Ajax Student基本信息:" ,resultData);
                resolve(resultData);

            },
            error(err) {
                console.log("promise 发出的异步请求异常: ", err);
            }
        })
      })

      //这里我们继续可以编写请求成功后的业务
      p.then((resultData) => {
          //这里我们可以继续发出请求
          console.log("p.then 得到ResultData",resultData);
          $.ajax({
            url:`data/Student_detail_${resultData.id}.json`,
            success(resultData) {
                console.log("第2次Ajax请求 Student的详细信息=",resultData);
            },
            error(err) {
                console.log("Promise发出的异步请求异常=", err);
            }
          })
      })
    </script> 

结果:

 其中Resolve函数名称也可以写成别的函数名字,只要前后保持一致也是可以运行的

所以这里的resolve只是个形参,具体的执行流程感兴趣的小伙伴可以看下源码。

其中我们可以在error中调用reject(err)。在p.then后面加上catch语句,这样不论是第一次请求还是第二次都能在catch语句中统一捕获抛出异常。

但要注意的是第二次请求的Promise对象要return出去,这样catch语句才能执行。

<script type="text/javascript">
      //先请求到Student.json
      //1. 创建Promise对象
      //2. 构造函数传入一个箭头函数
      //3.(resolve, reject)参数列表resolve: 如果请求成功,调用resolve函数
      //4. 如果请求失败,调用reject函数
      //5. 箭头函数体,仍然是通过jQuery发出了Ajax请求
      let p = new Promise((resolve,reject) => {
        //发出Ajax请求
        $.ajax({
            url:"data/Student.json",
            success(resultData) { //成功的回调函数
                console.log("promise发出的一次Ajax Student基本信息:" ,resultData);
                resolve(resultData);

            },
            error(err) {
              reject(err)
            }
        })
      })

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

接下来再新建一个studentfri.json

 

 这样演示第三次请求时依赖于第二次请求的结果,将使用模板字符串把resultData.fri获取到,然后去请求Student_fri_2.json。

  <script type="text/javascript">
      //先请求到Student.json
      //1. 创建Promise对象
      //2. 构造函数传入一个箭头函数
      //3.(resolve, reject)参数列表resolve: 如果请求成功,调用resolve函数
      //4. 如果请求失败,调用reject函数
      //5. 箭头函数体,仍然是通过jQuery发出了Ajax请求
      let p = new Promise((resolve,reject) => {
        //发出Ajax请求
        $.ajax({
            url:"data/Student.json",
            success(resultData) { //成功的回调函数
                console.log("promise发出的一次Ajax Student基本信息:" ,resultData);
                resolve(resultData);

            },
            error(err) {
              reject(err)
            }
        })
      })

      //这里我们继续可以编写请求成功后的业务
      p.then((resultData) => {
          //这里我们可以继续发出请求
         // console.log("p.then 得到ResultData",resultData);
         return new Promise((resolve, reject) => {
            $.ajax({
            url:`data/Student_detail_${resultData.id}.json`,
            success(resultData) {
                console.log("第2次Ajax请求 Student的详细信息=",resultData);
                resolve(resultData);
            },
            error(err) { //第二次Ajax请求失败的回调函数 依赖于第一次请求的结果
                reject(err)
        
            }
          })
         })
          
      }).then((resultData) => {
        console.log("p.then().then(), resultData",resultData)
        //即可以在这里发送第三次Ajax请求 依赖于第二次发出的结果 去获取他的朋友
       return new Promise((resolve,reject) =>{
        $.ajax({
            url:`data/Student_fri_${resultData.fri}.json`,
            success(resultData) { //第二次请求成功,回调函数
                console.log("第3次Ajax请求,student的friend",resultData);

            },error(err){
                reject(err)
            }
        })
       })

      })
      .catch((err)=> {
        console.log("Promise发出的异步请求异常=", err);
      })
    </script> 

结果:

这就是使用Promise发出Ajax请求的流程。但是代码看起来比较臃肿

我们对Promise进行代码重排。

  <script type="text/javascript">
      /**将重复的代码抽取出来,编写一个方法get
       * @param url ajax请求的资源
       * @param data ajax请求携带的数据
       * 
       */
         function get(url, data) {
          return new Promise((resolve, reject)=>{
            $.ajax({
              url:url,
              data:data,
              success(resultData) {
                resolve(resultData);
              },
              error(err){
                reject(err);
              }
            })
          })
         }  
         
         get("data/Student.json").then((resultData)=>{
          //第1次Ajax请求成功后的处理代码
          console.log("第一次Ajax请求返回的数据:" ,resultData);
          return get(`data/Student_detail_${resultData.id}.json`);

         }).then((resultData)=> {
          //第2次Ajax请求成功后的处理代码
          console.log("第2次Ajax请求成功后返回的数据:" ,resultData);
          return get(`data/Student_fri_${resultData.fri}.json`);

        }).then((resultData) => {
          console.log("第三次ajax请求返回的数据=", resultData);
        }).catch((err)=>{
             console.log("Promise请求异常",err)
        })

    </script> 

猜你喜欢

转载自blog.csdn.net/m0_56653797/article/details/129777433