• Promise


    1,Promise A+规范

    1,所有的异步场景,都应该看做是一个异步任务

    在 js 中表现为一个对象——Promise 对象。也就是任务对象。

    2,Promise 对象有2个阶段,3个状态

    在这里插入图片描述
    1,任务创建

    • 任务总是从未决阶段 --> 已决阶段,无法逆行。
    • 任务总是从挂起状态 --> 完成或失败状态,无法逆行。
    • 任务一开始都是 pending 状态,任务一旦完成或失败,状态不能再被改变
    const result = new Promise((resolve, reject) => {
      resolve(1);
      reject(2); // 无效
      resolve(3); // 无效
      console.log(123); // 正常执行
    });
    console.log(result); // Promise {: 1}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2,更改状态

    • pending --> fulfilled 称为 resolve(data)
    • pending --> rejected 称为 reject(reason)

    3,后续处理

    • fulfilled 的后续处理,称为 onFulfilled
    • rejected 的后续处理,称为 onRejected

    在这里插入图片描述

    2,Promise 简单API

    1,创建任务

    const pro = new Promise(() => {
      console.log('会被立即执行的函数');
    })
    console.log(pro) // Promise {  }
    
    • 1
    • 2
    • 3
    • 4

    2,更改状态

    const pro = new Promise((resolve, reject) => {
      console.log('会被立即执行的函数')
      setTimeout(() => {
        if (Math.random() < 0.5) {
          resolve('成功') // 从 pending 状态 --> fulfilled 状态
        } else {
          reject('失败') // 从 pending 状态 --> rejected 状态
        }
      }, 1000);
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3,后续处理

    pro.then(
      // fulfilled 的回调函数
      (data) => {
        console.log(data)
      },
      // rejected 的回调函数
      (reason) => {
        console.log(reason)
      }
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    实践举例:delay 延迟工具函数

    function delay(duration) {
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve();
        }, duration);
      });
    }
    
    await delay(3000)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3,链式调用

    在这里插入图片描述
    通过 then()catch() 函数做后续处理。

    promise.then(
      // fulfilled 的回调函数
      (data) => {
        console.log(data)
      },
      // rejected 的回调函数
      (reason) => {
        console.log(reason)
      }
    )
    
    // 相当于
    promise
      .then(
        // fulfilled 的回调函数
        (data) => {
          console.log(data);
        }
      )
      .catch(
        // rejected 的回调函数
        (reason) => {
          console.log(reason);
        }
      );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    常见写法:

    /*
     * 任务成功后,执行处理1,失败则执行处理2
     */
    promise.then(处理1).catch(处理2)
    
    /*
     * 任务成功后,依次执行处理1、处理2,若 promise 任务失败 或 处理1和2有错,都会执行处理3
     */
    promise.then(处理1).then(处理2).catch(处理3)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    特性:

    3.1,then()必定返回一个新 Promise 对象(新任务)。

    根据上面的等效写法,catch() 也会返回一个新 Promise 对象(新任务)。

    3.2,新任务的状态,取决于前任务的后续处理。

    • 若没有相关的后续处理,新任务的状态和前任务一致,数据为前任务的数据。

    换句话说,不相关的后续处理函数不会执行。

    下面的例子中,因为 Promise 一开始的状态时 pendingsetTimeout 为了获取最终状态。
    至于 setTimeout 为什么可以获取,参考事件循环机制

    举例1,promise1fulfilled 状态,但却没有 then() 做对应的后续处理。

    const promise1 = new Promise((resolve) => {
      resolve(1);
    });
    const promise2 = promise1.catch(() => {
      console.log("不会被打印");
    });
    
    setTimeout(() => {
      console.log(promise2); // Promise {: 1}
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    举例2,promise1rejected 状态,但却没有 catch() 做对应的后续处理。

    const promise1 = new Promise((resolve, reject) => {
      reject(1);
    });
    const promise2 = promise1.then(() => {
      console.log("不会被打印");
    });
    
    setTimeout(() => {
      console.log(promise2); // Promise {: 1}
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 若有后续处理但还未执行,新任务挂起
    const promise1 = new Promise((resolve) => {
      console.log(1);
      setTimeout(() => {
        resolve();
      }, 1000);
    });
    const promise2 = promise1.then(() => {
      console.log(2);
    });
    
    setTimeout(() => {
      console.log(promise2);
    });
    
    // 1
    // Promise {}
    // 2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 若后续处理执行了,则根据后续处理的情况确定新任务的状态:
      • 后续处理执行无错,新任务的状态为完成,数据为后续处理的返回值(没有返回,就是 undefined)
      • 后续处理执行有错,新任务的状态为失败,数据为异常对象
      • 后续执行后返回的是一个任务对象,新任务的状态和数据与该任务对象一致

    第1种情况举例:

    const promise1 = new Promise((resolve) => {
      resolve();
    });
    const promise2 = promise1.then(() => {
      return 123;
    });
    
    setTimeout(() => {
      console.log(promise2); // Promise {: 123}
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    const promise1 = new Promise((resolve, reject) => {
      reject();
    });
    const promise2 = promise1.catch(() => {
      return 123;
    });
    
    setTimeout(() => {
      console.log(promise2); // Promise {: 123}
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    第2种情况举例,catch 同理。

    const promise1 = new Promise((resolve) => {
      resolve();
    });
    const promise2 = promise1.then(() => {
      throw "一个错误";
    });
    
    setTimeout(() => {
      console.log(promise2); // Promise {: '一个错误'}
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    第3种情况举例,

    const promise1 = new Promise((resolve) => {
      resolve();
    });
    const promise2 = promise1.then(() => {
      // promise2 的状态取决于这个 Promise 对象的状态
      return new Promise((resolve, reject) => {
        resolve(1);
      });
    });
    
    setTimeout(() => {
      console.log(promise2); // Promise {: 1}
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    一道面试题

    const result = new Promise((resolve) => {
      resolve(1);
    })
      .then((res) => {
        console.log(res); // 1
        return new Error(2); // 注意,这不是报错,而是一个对象
      })
      // 不执行
      .catch((err) => {
        throw err;
      })
      // 对上一个 then 返回的 Promise 做了处理,但没有返回结果。
      .then((res) => {
        console.log(res);
      });
    
    setTimeout(() => {
      console.log(result); // Promise {: undefined}
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    3,Promise 静态方法

    任务即 Promise 对象

    静态方法作用
    Promise.resolve()直接返回 fulfilled 状态的任务
    Promise.reject()直接返回 rejected 状态的任务
    Promise.all(任务数组)返回一个数组
    任务全部成功则成功
    任何一个失败则失败
    Promise.any(任务数组)返回一个任务
    任何一个成功则成功
    任务全部失败则失败,并返回一个数组
    Promise.race(任务数组)返回一个任务
    只要有一个进入已决状态,则已决,状态和其一致
    Promise.allSettled(任务数组)返回一个数组
    任务数组全部已决则成功
    该任务不会失败

    主要介绍下 Promise.allSettled(任务数组)

    1,当任务数组都变为已决状态,则返回每个任务的结果。

    Promise.allSettled([
      Promise.resolve(1),
      Promise.reject(2),
      new Promise((resolve) => {
        resolve(3)
      })
    ]).then((values) => {
      console.log(values);
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    结果:
    在这里插入图片描述

    2,当任务数组中有一个未决,则永远处于 pending 状态。

    Promise.allSettled([
      Promise.resolve(1),
      Promise.reject(2),
      new Promise(() => {})
    ]).then((values) => {
      console.log(values); // then() 永远不被执行
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    实用举例:需要获取所有的请求结果,有失败的请求没有关系,最后能获取所有成功的数据即可。

    // 模拟请求
    function getData(pageIndex) {
      return new Promise((resolve, reject) => {
        if (Math.random() < 0.4) {
          reject("网络错误");
        }
    
        setTimeout(() => {
          resolve(pageIndex);
        }, Math.floor(Math.random() * 3000));
      });
    }
    
    const arr = [];
    for (let i = 0; i < 5; i++) {
      arr.push(getData(i));
    }
    
    Promise.allSettled(arr).then((values) => {
      console.log(values);
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    结果
    在这里插入图片描述

    4,async 和 await

    async

    1,async 关键字用于修饰函数,被它修饰的函数,一定返回 Promise 对象。

    async function fun() {}
    console.log(fun()) // Promise {: undefined}
    
    async function fun2() {
      await 1
    }
    console.log(fun2()) // Promise {}。因为有异步代码
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2,若执行过程报错,则任务是 rejected

    async function fun() {
      throw new Error(1);
    }
    console.log(fun()); // Promise {: Error: 1
    
    • 1
    • 2
    • 3
    • 4

    3,当 async 修饰的函数中明确返回了 Promise 对象,则该函数相当于没有被 async 修饰。

    async function fun() {
      return new Promise((resolve) => {
        resolve(1);
      });
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    await

    1,await 用于等待一个 Promise 对象已决后,获取已决后的结果,如果结果为 rejected 状态,则抛出异常,可以用 try...catch 捕获。

    async function fun() {
      try {
        await Promise.reject(1);
      } catch (error) {
        console.log('error:' + error);
      }
    }
    fun() // error:1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2,因为 await 需要放到异步函数中,所以可以用立即执行函数。

    (async ()=> {
      await delay(1000)
      console.log('等待1s后执行后续操作');
    })()
    
    • 1
    • 2
    • 3
    • 4

    3,当 await 后的表达式的值不是 Promise,await 会把该值转换为 fulfilled 状态的 Promise,然后返回其结果。

    await 1 //相当于 await Promise.resolve(1)
    
    • 1

    5,面试题

    面试题


    以上。

  • 相关阅读:
    天猫超市电商营销系统:无代码开发实现API连接集成
    网络安全事件应急响应实战
    软件测试Jenkins部署与配置
    express快速入门【含源码压缩包下载】
    Power Automate-创建自定义连接器
    【Vue3】全局组件,递归组件,动态组件,传送组件,缓存组件,异步组件等
    【Java】已解决java.nio.channels.FileLockInterruptionException异常
    Excel下拉填充时,如何使得数字不递增?
    手动关闭PS中的TopazStudio2的登录窗口
    操作系统高频面试题(2022最新整理)
  • 原文地址:https://blog.csdn.net/qq_40147756/article/details/132711878