Promise原理

一、Promise与异步的关系

之前做练习遇到Promise与SetTimeout的混合使用,自己发现对于Promise的理解不够彻底,所以今天就来看看这方面的问题。
首先Promise的主要作用是能够处理异步问题,那么什么是异步呢?与它相反的同步又是怎么理解的呢?

1.1 同步与异步概念

1.1.1 同步

单线程按顺序执行,执行步骤有明确的先后顺序。
例如开车,需要先进车门,发动引擎再驾驶。这三部就是有明确的先后顺序,一步步执行下来。
js碰到的一般场景是单线程顺序执行的。

1.1.2 异步

该步骤不进入主线程,而是把需要执行的步骤先挂在队列中。等主线程有执行空间,再进行执行操作。
例如上述例子,某人在进车门时收到短信需要回复,他把回复操作挂在进车门,发动引擎之后才操作。
js要是使用到setTimeout,请求接口ajax相关的操作会碰到异步操作。

1.2 Promise为什么能解决异步问题?

要是遇到多个异步进行嵌套,会产生回调地狱(回调地狱会造成维护性能差,多次重复操作可读性差)
而ES6中的Promise被列为正式规范就是为了解这个问题,并且可以制定多种异步的执行规则或多种状态判断执行结果。

二、Promise原理

2.1 Promise是什么对象?

我们先使用console.dir(promise)可以打印出该对象的所有属性以及相关属性值。
在这里插入图片描述
可以看出promise是一个构造函数,所以每次使用都需要new新建实例。
观察打印结果,看到它本身含有reject、resolve方法。在原型上又有then、catch方法。

2.2 promise的简单使用

在这里插入图片描述

从上述代码中可以看出来,Promise构造函数中有两个参数(resolve, reject)。这两个参数与Promise的三种状态有关。

Promise的三种状态:

  • pending(进行中)
  • fulfilled(执行成功)
  • rejected(执行失败)。

在执行Promise的时候:即进入队列中,它的状态会是pending,会根据执行结果返回fulfilled或者rejected。(注意:当次Promise三种状态只能存在一种,最终结果不是fulfilled就是rejected,而且Promise状态不可回滚)

在count()后面会看到执行了它的两种方法:

  • .then()方法,这就是链式调用该Promise(即op)中的执行成功resolve()中的参数。反正要是执行失败就是取reject()中的参数。
  • .catch()方法,这个作用就是当在执行上述.then()中报错时会抛出异常(控制台不会看到报错信息),就是会执行.catch()方法里面的代码。

2.3 使用Promise来实现链式调用

<script>
export default {
  data(){
    return{

    }
  },
  mounted(){
    // 2.3 使用Promise来实现链式调用
    this.promise1().then((outPrint) => {
      console.log(outPrint)
      this.promise2().then(
      //第一,resolve参数
      (outPrint2) => {
        console.log(outPrint2)
        return this.promise3()
      },
      //第二,reject参数
      (outPrint2) => {
        console.log(outPrint2)
        return this.promise3()
      })
    })
  },
  methods:{
    // 2.3 使用Promise来实现链式调用
    promise1(){
      var op1 = new Promise( (resolve,reject) => {
        //异步操作
        setTimeout(()=>{
          console.log('我是promise1内部的console')
          resolve('我从promise1里面出来了')
        },2000)
      })
      return op1
    },

    promise2(){
      var op2 = new Promise( (resolve,reject) => {
        //异步操作
        setTimeout(()=>{
          console.log('我是promise2内部的console')
          reject('我从promise2里出来reject')
        },2000)
      })
      return op2
    },

     promise3(){
      var op3 = new Promise( (resolve,reject) => {
        //异步操作
        setTimeout(()=>{
          console.log('我是promise3内部的console')
          // resolve('我从promise3里面出来了')
        },2000)
      })
      return op3
    }
  }
}
</script>

运行截图:
在这里插入图片描述

由此可以看出该promise比相对的回调函数嵌套可读性已经复杂度减少了不少,即简单又灵活。

2.4 使用Promise.all,Promise.race

实例化好每个promise之后,可以使用Promise.all([实例1,实例2,实例3]),以数组的形式进行传入,这样可以并行执行多个异步操作。最终.then()中返回的参数res,也是以数组的形式进行把resolve()中的参数返回出来。Promise.race([])也是如此使用。

<script>
export default {
  data(){
    return{

    }
  },
  mounted(){
    this.comA()
    this.comR()
  },
  methods:{
    comA(){
      console.time('timeRangeA')
      Promise.all([this.promise1(), this.promise2(),this.promise3()])
      .then( (res) => {
        console.log(res)
        console.timeEnd('timeRangeA')
      } )
    },

    comR(){
      console.time('timeRangeR')
      Promise.race([this.promise1(), this.promise2(),this.promise3()])
      .then( (res) => {
        console.log(res)
        console.timeEnd('timeRangeR')
      } )
    },

    promise1(){
      var op1 = new Promise( (resolve,reject) => {
        //异步操作
        setTimeout(()=>{
          resolve('我从promise1里面出来了')
        },10000)
      })
      return op1
    },

    promise2(){
      var op2 = new Promise( (resolve,reject) => {
        //异步操作
        setTimeout(()=>{
          resolve('我从promise2里面出来了')
        },1000)
      })
      return op2
    },

     promise3(){
      var op3 = new Promise( (resolve,reject) => {
        //异步操作
        setTimeout(()=>{
          resolve('我从promise3里面出来了')
        },2000)
      })
      return op3
    }
  }
}
</script>

运行截图:
在这里插入图片描述

2.4.1 all与race的区别

  • all是以谁最慢的时间进行输出,如上述代码promise1()是延迟10秒输出,三者最慢。最后执行.then()的时间也是10秒左右,promise2()与promise3()等待promise1()执行完再输出。
  • race是以谁最快的时间进行输出,如上述代码promise2()是延迟1秒输出,而promise2()执行完直接不等待promise1()与promise3(),直接执行.then()。

2.4.2 all与race的使用场景

  • all:渲染一个页面,需要把所有的图片等资源全部获取完再显示页面。
  • race:接口请求获取一个资源,要是请求超时,直接不再请求此资源并弹出请求超时。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值