ES6之Promise实战,让你的多次请求更清晰

Posted lovoo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ES6之Promise实战,让你的多次请求更清晰相关的知识,希望对你有一定的参考价值。

前言

在实际开发中,我们经常会在发送一个请求后,得到反馈,再进行一下次请求,再得到反馈,又再进行下一次请求,每次的代码都在ajax内部的success实现,这样看起来繁琐,容易造成数据通信堵塞。如何解决这个问题呢?这时我们就可以利用Promise来解决!

在开始深入学习Promise前,熟悉JS Event Loop的机制是非常有必要的,如果你对Event Loop还不熟悉,非常推荐你先阅读javascript之多线程和Event Loop这篇文章,会对你更好理解Promise执行顺序帮助很大!

什么是Promise?

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。

古人云:“君子一诺千金”,所谓Promise,正如其中文含义,简单说就是一个承诺,“承诺将来会执行”约定的事情。

从语法上说,Promise 是一个对象,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

Promise也有一些缺点。首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。第三,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

约定
不同于“老式”的传入回调,在使用 Promise 时,会有以下约定:

在本轮 Javascript event loop(事件循环)运行完成之前,回调函数是不会被调用的。

  • 通过then()添加的回调函数总会被调用,即便它是在异步操作完成之后才被添加的函数。
  • 通过多次调用then(),可以添加多个回调函数,它们会按照插入顺序一个接一个独立执行。
  • 因此,Promise 最直接的好处就是链式调用(chaining)。

Promise的使用

一个Promise的三种状态
在开始使用Promise之前,我们首先需要了解Promise的三种状态:

pending: 初始状态,既不是成功,也不是失败状态。
fulfilled: 意味着操作成功完成。
rejected: 意味着操作失败。

pending 状态的 Promise 对象可能会变为fulfilled 状态并传递一个值给相应的状态处理方法,也可能变为失败状态(rejected)并传递失败信息。当其中任一种情况出现时,Promise 对象的 then 方法绑定的处理方法(handlers )就会被调用(then方法包含两个参数:onfulfilled 和 onrejected,它们都是 Function 类型。当Promise状态为fulfilled时,调用 then 的 onfulfilled 方法,当Promise状态为rejected时,调用 then 的 onrejected 方法, 所以在异步操作的完成和绑定处理方法之间不存在竞争)。

因为Promise.prototype.then和Promise.prototype.catch方法返回promise 对象, 所以它们可以被链式调用。
在这里插入图片描述

Promise实战

有这么个需求,根据查询某个用户的课程得分。

如下图,有三个json文件,首先请求用户获取用户,然后通用户id查询到其课程信息Id,然后根据课程Id,获取当前课程的得分
在这里插入图片描述
user.json:

{
  "id": "1",
  "name": "tom",
  "age": 20
}

user_course_1.json

{
  "id": "1",
  "userId": "1",
  "title": "java"
}

course_score_1.json

{
  "id": "1",
  "courseId": "1",
  "score": 50
}

以前的实现方法

<script>
      /**
       * 1.查询当前用户信息
       * 2.按照当前用户的id查出他的课程
       * 3.按照当前课程id查询出分数
       */
      $.ajax({
        url:'mall-vue/src/views/demo/promise/user.json',
        success(data){
          $.ajax({
            url:'mall-vue/src/views/demo/promise/user_coure_${data.id}.json',
            success(data){
              $.ajax({
                url:'mall-vue/src/views/demo/promise/course_score_{data.id}.json',
                success(data){
                  console.log(data.score)
                },
                error(err){
              
                }
              })
            },
            error(err){

            }
          })
        },
        error(err){

        }
      })

</script>

使用Promise实现

在每一次成功,才进行一下请求

const p = new Promise(function(resolve, reject) {
        $.ajax({
          url:'mall-vue/src/views/demo/promise/user.json',
          success(data){
            console.log("查询用户成功!=用户名称==", data.name)
            resolve(data);
          },
          error(err){
            reject(error);
          }
        })

p.then(function(data)){
    return new Promise(function(resolve, reject) {
      $.ajax({
        url:'mall-vue/src/views/demo/promise/user_coure_${data.id}.json',
        success(data){
          console.log("查询课程成功!=课程名称==", data.title)
          resolve(data);
        },
        error(err){
          reject(error);
        }
      })
    })

  },function(error){

  }

}).then(function(data){
  $.ajax({
    url:'mall-vue/src/views/demo/promise/course_score_{data.id}.json',
    success(data){
      console.log("查询分数成功!=分数==", data.score)
    },
    error(err){
  
    }
  })
})

将上述代码优化封装:

function get(url, data){
        return new Promise((resolve, reject) => {
            $.ajax({
              url: url,
              success(data){
                resolve(data);
              },
              error(err){
                reject(error);
              }
            })
        })
      }

得到简化版:

//上述代码简写:
 get(`user.json`)
   .then((data) => {
       console.log("查询用户成功!=用户名称==", data)
       return get(`user_course_${data.id}.json`)
   })
   .then((data) => {
       console.log("查询课程成功!=课程名称==", data)
       return get(`course_score_${data.id}.json`)
   })
   .then((data) => {
     console.log("查询分数成功!=分数==", data)
   })
   .catch((err) => {
     console.log("出现异常:", err)
        })

以上是关于ES6之Promise实战,让你的多次请求更清晰的主要内容,如果未能解决你的问题,请参考以下文章

ES6新增特性——Promise

ES6几大特性,让你的代码更优美

ES6几大特性,让你的代码更优美

高效学习ES6,让你的代码更优雅

es6从零学习:promise

ES6之Promise封装ajax()