Promise-异步请求封装处理

什么是Promise呢?

ES6中一个非常重要和好用的特性就是Promise

  • 但是初次接触Promise会一脸懵逼,这TM是什么东西?
  • 看看官方或者一些文章对它的介绍和用法,也是一头雾水。

Promise到底是做什么的呢?

  • Promise是异步编程的一种解决方案。
    那什么时候我们会来处理异步事件呢?
  • 一种很常见的场景应该就是网络请求了。
  • 我们封装一个网络请求的函数,因为不能立即拿到结果,所以不能像简单的3+4=7一样将结果返回。
  • 所以往往我们会传入另外一个函数,在数据请求成功时,将数据通过传入的函数回调出去。
  • 如果只是一个简单的网络请求,那么这种方案不会给我们带来很大的麻烦。

但是,当网络请求非常复杂时,就会出现回调地狱。
OK,我以一个非常夸张的案例来说明。

网络请求的回调地狱

我们来考虑下面的场景(有夸张的成分):

  • 我们需要通过一个url1从服务器加载一个数据data1,data1中包含了下一个请求的url2
  • 我们需要通过data1取出url2,从服务器加载数据data2,data2中包含了下一个请求的url3
  • 我们需要通过data2取出url3,从服务器加载数据data3,data3中包含了下一个请求的url4
  • 发送网络请求url4,获取最终的数据data4

在这里插入图片描述
上面的代码有什么问题吗?

  • 正常情况下,不会有什么问题,可以正常运行并且获取我们想要的结果。
  • 但是,这样额代码难看而且不容易维护。
    我们更加期望的是一种更加优雅的方式来进行这种异步操作。
    如何做呢?就是使用Promise。
  • Promise可以以一种非常优雅的方式来解决这个问题。

Promise基本语法

这里,我们用一个定时器来模拟异步事件:
假设下面的data是从网络上1秒后请求的数据

<script>
  // 1.使用setTimeout 模拟异步请求

  // 假如现在有三个嵌套的网络请求,一般的做法。这个时候的结构就相当的复杂了
  setTimeout(() => {
    console.log("Hello word")
    console.log("Hello word")
    console.log("Hello word")
    // .. 此处省略1w行代码

    setTimeout(() => {
      console.log("hello vue.js")
      console.log("hello vue.js")
      console.log("hello vue.js")
      // .. 此处省略1w行代码

      setTimeout(() => {
        console.log("hello java")
        console.log("hello java")
        console.log("hello java")
        // .. 此处省略1w行代码
      }, 1000)
    }, 1000)
  }, 1000)
</script>

console.log就是我们的处理方式。
这是我们过去的处理方式,我们将它换成Promise代码

  <script>
 new Promise((resolve, reject) => {

    // 第一次网络请求代码
    setTimeout(() => {
      resolve() // 当执行这个函数时,就会调用下面的then函数
    }, 1000)
  }).then(() => {

    // 第一次网络请求回调
    console.log("Hello word")
    console.log("Hello word")
    console.log("Hello word")
    // .. 此处省略1w行代码

    // then() 的返回值 又是一个Promise
    return new Promise((resolve, reject) => {
      // 第二次网络请求
      setTimeout(() => {
        resolve() // 当执行这个函数时,就会调用下面的then函数
      }, 1000)
    })
  }).then(() => {

    console.log("hello vue.js")
    console.log("hello vue.js")
    console.log("hello vue.js")
    // .. 此处省略1w行代码
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve();
      }, 1000)
    })
  }).then(() => {

    console.log("hello java")
    console.log("hello java")
    console.log("hello java")
    //       // .. 此处省略1w行代码
  })

  // 所有的网络请求代码都放在Promise对象里面
  // 所有的回调处理代码都放在上一次Promise对应的then()函数里面
  </script>

一般情况下时有异步操作时才用到Promise对异步操作进行封装。
异步操作之后会有三种状态
我们一起来看一下这三种状态:
pending:等待状态,比如正在进行网络请求,或者定时器没有到时间。
fulfill:满足状态,当我们主动回调了resolve时,就处于该状态,并且会回调.then()
reject:拒绝状态,当我们主动回调了reject时,就处于该状态,并且会回调.catch()
在这里插入图片描述

简单使用


  new Promise((resolve, reject) => {
    setTimeout(() => {
      // 成功的时候调用resolve,执行then
      resolve('resolve');
      // 失败的时候调用reject,执行catch
      reject('err');
    }, 1000)
  }).then((date) => {
    console.log(date);
  }).catch((err) => {
    console.log(err)
  })

另一种使用方式

  new Promise((resolve, reject) => {
    setTimeout(() => {
      // 成功的时候调用resolve,执行then
      resolve('resolve');
      // 失败的时候调用reject,执行catch
      reject('err');
    }, 1000)
  }).then((data) => {
    // 成功时执行
    console.log(data)
  }, err => {
    // 失败时执行
    console.log(err)
  })

Promise all的使用

当需要两个或以上网络请求同时都成功时。再执行回调


  Promise.all([
    new Promise((resolve, reject) => {
      $.ajax({
        url: 'url1',
        success: function (data) {
          resolve(data)
        }
      })
    }),
    new Promise((resolve, reject) => {
      $.ajax({
        url: 'url2',
        success: function (data) {
          resolve(data)
        }
      })
    })
  ]).then((result => {
    console.log(result[0]);// 第一次请求的结果
    console.log(result[1]);// 第二次请求的结果
  }))
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值