ES6-Promise异步请求解决方案

小灶

  • 前言
  • 为什么使用Promise
  • 什么是promise
  • 运用Promise
  • Promise.all
  • ES7 await / async

IT基础系列


前言

这是一门知识补充课

我们编写的JavaScript代码实际上是单线程的程序,那就决定了我们的代码是一行一行的顺序执行的,处理一些简短、快速的运算操作时主线程就够了,如果在同步程序中发送了网络请求,如果超时了,下面的代码依赖于网络请求,那么整个网页将会失去响应。

而异步的概念则与同步恰恰相反,一个异步过程的执行将不再与原有的序列有顺序关系,特别是对发送网络请求,不确保响应时间时候,异步是最优选择,网络请求无论多长时间,程序将不会在此等待,直接走下面的代码,等异步的请求有了响应,主线程几乎不用关心异步任务的状态了,自己完成回调后续的操作,程序间互不影响。

简单来理解:同步按你的代码顺序执行,异步不按照代码顺序执行,异步的执行效率更高。

ES6-Promise异步请求解决方案_第1张图片

现在是前端常用的方式–异步

为什么使用Promise

“回调地狱”这个词,不知道大家听过没有,就是异步调用获取到结果后,为下一个异步函数提供参数,所以就会一层一层的出现回调里面嵌入回调,导致层次很深,代码维护起来特别的复杂

以一个uni 案例

getData(){
  //获取分类列表id
  uni.request({
    url:"https://ku.qingnian8.com/dataApi/news/navlist.php",
    success:res=>{
      let id=res.data[0].id
      // 根据分类id获取该分类下的所有文章
      uni.request({
        url:"https://ku.qingnian8.com/dataApi/news/newslist.php",
        data:{
          cid:id
        },
        success:res2=>{
          //获取到一篇文章的id,根据文章id找到该文章下的评论
          let id=res2.data[0].id;
          uni.request({
            url:"https://ku.qingnian8.com/dataApi/news/comment.php",
            data:{
              aid:id
            },
            success:res3=>{
              //找到该文章下所有的评论
              console.log(res3)
            }
          })
        }
      })

    }
  })
}

这个代码中出现了嵌套,俄罗斯套娃。后期维护麻烦

用函数封装的思想,封装请求

调用部分

//在onload初始化后调用相应的函数
onLoad() {
  //调用导航函数,并拿到函数的返回值
  this.getNav(res=>{
    let id=res.data[0].id;
    //拿到分类id作为参数
    this.getArticle(id,res2=>{
      //拿到文章id作为参数
      let id=res2.data[0].id;
      this.getComment(id,res3=>{
        //最终获取到第一个分类下,第一篇文章下,所有评论
        console.log(res3)
      })
    })
  });
}

封装部分

methods: {
    //先获取导航分类接口,将结果进行返回,到调用函数的地方获取
    getNav(callback){
      uni.request({
        url:"https://ku.qingnian8.com/dataApi/news/navlist.php",
        success:res=>{
          callback(res)
        }
      })
    },

    //获取文章数据,将文章列表进行返回
    getArticle(id,callback){
      uni.request({
        url:"https://ku.qingnian8.com/dataApi/news/newslist.php",
        data:{
          cid:id
        },
        success:res=>{
          callback(res)
        }
      })
    },

      //获取文章下的所有评论
      getComment(id,callback){
        uni.request({
          url:"https://ku.qingnian8.com/dataApi/news/comment.php",
          data:{
            aid:id
          },
          success:res=>{
            callback(res)
          }
        })
      }
}

看上面大家可能都看懵了,仔细看来,并没有解决回调地狱的问题,还是回调里面嵌套回调,只是把函数独立出来了,看着清晰条理了一些而已,但是维护难度还是有的,说以随着ES6的普及,这种方案逐渐边缘化,取而代之的就是Promise方案了。

什么是promise

promise是解决异步的方法,本质上是一个构造函数,可以用它实例化一个对象。

对象身上有resolverejectall,原型上有thencatch 方法。

promise对象有三种状态:pending(初识状态/进行中)、resolvedfulfilled(成功)、rejected(失败)**

  1. pending。它的意思是 “待定的,将发生的”,相当于是一个初始状态。创建Promise对象时,且没有调用resolve或者是reject方法,相当于是初始状态。这个初始状态会随着你调用resolve,或者是reject函数而切换到另一种状态。
  2. image.png
  3. resolved。表示解决了,就是说这个承诺实现了。 要实现从pendingresolved的转变,需要在 创建Promise对象时,在函数体中调用了resolve方法
  4. image.png
  5. rejected。拒绝,失败。表示这个承诺没有做到,失败了。要实现从pendingrejected的转换,只需要在创建Promise对象时,调用reject函数。
  6. image.png

浏览器打印 promise 结果:
ES6-Promise异步请求解决方案_第2张图片


运用Promise

异步请求2.0

.then 的链式调用函数

//promise链式调用
this.getNav().then(res=>{
  let id=res.data[0].id;
  return this.getArticle(id);
}).then(res=>{
  let id=res.data[0].id;
  return this.getComment(id)
}).then(res=>{
  console.log(res)
})

函数返回 promise 对象

methods: {
    //先获取导航分类接口,将结果进行返回,到调用函数的地方获取
    getNav(callback){
      return new Promise((resolve,reject)=>{
        uni.request({
          url:"https://ku.qingnian8.com/dataApi/news/navlist.php",
          success:res=>{
            resolve(res)
          },
          fail:err=>{
            reject(err)
          }
        })
      })
    },

    //获取文章数据,将文章列表进行返回
    getArticle(id){
      return new Promise((resolve,reject)=>{
        uni.request({
          url:"https://ku.qingnian8.com/dataApi/news/newslist.php",
          data:{
            cid:id
          },
          success:res=>{
            resolve(res)
          },
          fail:err=>{
            reject(err)
          }
        })
      })
    },

      //获取文章下的所有评论
      getComment(id){
        return new Promise((resolve,reject)=>{
          uni.request({
            url:"https://ku.qingnian8.com/dataApi/news/comment.php",
            data:{
              aid:id
            },
            success:res=>{
              resolve(res)
            },
            fail:err=>{
              reject(err)
            }
          })
        })
}

改造一番后,代码可读性得到了提升,尽管代码量增加了,但是,优雅!

如果你觉得,这种调用方式还是有嵌套不够清晰,还有大杀器,就是目前最为流行的await/async了,这是ES7新引入的概念。

异步请求:谁响应快谁先打印出来

Promise.all

封装多个对象统一处理

直接 Promise.all([]) 放入数组

有助于做页面加载状态统一显示
页面中各个模块加载完毕之后,再显示

ES7 await / async

这两个命令是成对出现的

如果使用await没有在函数中使用async命令,那就会报错

如果直接使用async没有使用await不会报错,只是返回的函数是个promise,可以,但是没有意义

async onLoad() {
  let id,res;
  res=await this.getNav();
  id=res.data[0].id;
  res=await this.getArticle(id);
  id=res.data[0].id;
  res=await this.getComment(id);
  console.log(res)
}

你可能感兴趣的:(前端,es6,javascript,前端,Promise)