• 聊聊Promise的使用


    Promise

    Promise诞生的原因

    • 回调地狱
    1. 代码臃肿,可读性差。
    2. 代码耦合度高,可维护性差,难以复用
    3. 回调函数都是匿名函数,不方便调试

    Promise的生命周期

    • 每一个Promise对象都有三种状态,即Pending\fulfilled和rejected

    状态一旦改变就不能再做更改了。

    Promise的基本用法

    • 需要注意的是Promise在创建后会立即调用,然后等待执行resolve()函数或者reject()函数来确定Promise最终状态。

    then()函数

    • 在上一轮then()函数内部return的值会作为下一轮函数接收的参数值。

    • then()函数中不能返回Promise()实例本身,否则会出现Promise()循环引用的问题,抛出异常。

    • 处理rejected状态的Promise的回调函数最好用catch()来做

    catch()函数

    • catch()就是为了错误而存在的。
    • 出现错误会自动执行reject

    Promise.all()

    const p = Promise.all([p1, p2, p3]);
    
    • 1

    p的状态由p1,p2,p3三个值共同决定,只有当三者全部都为fulfilled成功状态的时候,p的状态才会变成fulfilled状态,此时p1,p2,p3的值组成一个数组,作为p的then()函数的回调函数的参数。

    只要有一个是rejected,p的状态就变为rejected,此时第一个被reject的实例的返回值会作为p的catch()函数的回调函数的参数。

    • 当p1,p2,p3如果已经定义了catch()函数,那么当其中一个Promise状态变为rejected时,并不会触发Promise.all()函数的catch()函数。
    const p1 = new Promise((resolve, reject) => {
        resolve('success');
    })
        .then(result => result)
        .catch(e => e);
    
    const p2 = new Promise((resolve, reject) => {
        throw new Error('error');
    })
    	.then(result => result)
    	.catch(e => e);
    
    Promise.all([p1, p2])
        .then(result => console.log(result)) // ['success', Error: error]
        .catch(e => console.log(e));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    此时p2的状态是fulfilled,p1的状态也是fulfilled,所以出现的值是['success', Error: error]

    • Promise.all()用于多个Promise实例上,返回一个新的Promise实例,表示如果是多个Promise实例中有任何一个实例的状态发生改变,那么这个新实例的状态就随之改变,而最先改变的那个Promise实例的返回值将作为新实例的回调函数的参数。

    Promise.race()

    const p = Promise.race([p1, p2, p3])
    
    • 1

    只要其中有一个状态出现了变化,那就直接进行监听。

    • 应用场景:假如发送一个axios请求,在3秒后还没有收到请求成功的响应时,会自动处理成请求失败。
    const p1 = axios.get('/testUrl');
    const p2 = new Promise((resolve, reject) => {
      setTimeout(() => throw new Error('test'), 5000)
    })
    const p = Promise.race([p1, p2])
    p.then(console.log).catch(console.error)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    Promise.resolve()函数

    Promise.resolve('success'); == new Promise(resolve => resolve('promise'))
    
    • 1

    Promise.reject()函数

    Promise.reject('reject'); == new Promise(reject => reject('reject'))
    
    • 1

    Promise()用法实例

    1. Promise代码与同步代码一起执行
    const promise = new Promise((resolve, reject) => {
        console.log(1);
        resolve();
        console.log(2);
    });
    promise.then(() => {
        console.log(3);
    });
    console.log(4);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    • 首先执行同步代码
    • 然后执行微任务
    • 到resolve()并不会停顿
    1. 同一个Promise内,resolve()函数和reject()函数先后执行
    • 当第一个resolve or reject执行完毕之后就停止了,只能执行一次。
    1. 同一个Promise实例自身重复执行
    • 如果不是Promise.then().then(),而是同级出现,那就不会执行两次。
    const promise3 = new Promise((resolve, reject) => {
      setTimeout(() => {
        console.log('once');
        resolve('success');
      }, 1000)
    });
    
    const start = Date.now()
    promise3.then((res) => {
      console.log(res, Date.now() - start)
    })
    promise3.then((res) => {
      console.log(res, Date.now() - start)
    })
    /*
    once
    success 1021
    success 1022
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    1. 在then()函数中返回一个异常
    Promise.resolve()
        .then(() => {
            console.log(1);
            return new Error('error!!!');
        })
        .then((res) => {
            console.log(2);
            console.log('then: ', res);
        })
        .catch((err) => {
            console.log(3);
            console.log('catch: ', err);
        });
    /*
    1
    2
    then:  Error: error!!!
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 不同于throw一个错误,并不会执行catch()函数
    • 而是会将Error()作为一个参数值传递下去,然后在then()中打印出来。
    1. then()函数接收的参数不是一个函数
    Promise.resolve(1)
    	.then(2)
    	.then(Promise.resolve(3))
    	.then(console.log);
    // 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 在Promise的then()和catch()中,如果传递的是非函数,那么就会产生值穿透现象。

    值穿透 ==> 传递的值会被直接忽略掉,继续执行链式调用后续的函数。

    1. 两种方法处理rejected状态的Promise
    Promise.resolve()
        .then(function success (res) {
            throw new Error('error');
        }, function fail1 (e) {
            console.error('fail1: ', e);
        })
        .catch(function fail2 (e) {
            console.error('fail2: ', e);
        });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • then()函数的第二个函数不能捕获第一个函数中抛出的异常,而catch()函数却能捕获到第一个函数中抛出的异常。
  • 相关阅读:
    【Spring Web教程】SpringBoot 实现一应用多Tomcat容器
    我实践:搭建轻量git服务器的两个方案
    JavaScrip练习
    【自动驾驶】PETR 环境安装与测试
    【Seata】分布式事务问题和理论基础
    代码重构的一些理由
    用户登录Demo
    串口服务器和光纤交换机的区别
    在做事上面体现出来,您之心胸所在,心有惊雷而面不改色,可拜上将军---程序员
    C++:了解string类
  • 原文地址:https://blog.csdn.net/weixin_60789461/article/details/126495427