• Promise梳理


    一、Promise简单介绍与基本使用

    1.1 Promise是什么?

    promise是js中进行异步编程的新的解决方案。从语法层面来说,Promise是一个构造函数;从功能上来说,我们使用promise对象来封装一个异步操作并获取其成功/失败的结果值。简单说promise对象就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
    可以把promise对象想象成一个冰块,里面冻着一个梨子(异步任务),随着时间推移,冰块化了(异步任务结束,状态改变了),里面的梨子爆露出来了,之后就一直是这个梨子(promise对象状态不会再变了)
    在这里插入图片描述

    1.2 为什么要使用Promise?

    1.2.1 指定回调函数的方式更加灵活
    1. 旧的方式:必须在异步任务开始前,进行指定。
    const fs = require("fs");
    
    function read() {
      fs.readFile("./a.ts", (err, data) => {
        console.log(data);
      });
    }
    read();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    1. Promise:异步任务启动 => 返回Promise对象 => 给Promise对象指定回调函数(甚至可以在异步任务结束后指定多个回调函数)(备注:指的就是执行then,在then中指定回调函数)(异步任务启动:指的就是在excutor函数同步执行时,其中的异步任务启动)
    let p = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("OK");
      }, 3000);
    });
    // ........
    // 可以马上指定,也可以很久之后指定,都是一样的
    // ........
    // 指定回调1
    p.then((value) => {
      console.log(value);
    });
    // 指定回调2
    p.then((value) => {
      alert(value);
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    1.2.2 支持链式调用,可以解决回调地狱问题
    1. 什么是回调地狱? 回调函数嵌套调用,外部回调函数执行的结果是嵌套函数执行的条件
      在这里插入图片描述

    2. 回调地狱的缺点?不便于阅读理解,不便于异常处理

    1.3 Promise的状态改变

    1.3.1 PromiseState

    PromiseState是Promise对象的实例属性,表示Promise对象的状态。
    该属性是原生代码内置的,无法在外部手动直接修改,只有resolve和reject函数可以修改此值。
    可由初始状态pending => fulfilled,或由初始状态pending => rejected。
    只有这两种状态变化,且只能改变一次。
    无论成功还是失败都会有一个返回结果,一般把成功的结果数据称为value,失败的结果数据称为reason。

    1.3.2 PromiseResult

    PromiseResult是Promise对象的实例属性,表示Promise对象的结果值。保存的是异步任务失败/成功的结果,只有resolve和reject函数可以设定此值。

    1.3.3 Promise的工作流程

    注意:当在excutor函数中throw抛出异常时,promise对象将变为失败状态,结果为该错误对象(即等同于reject)。
    在这里插入图片描述

    二、Promise的API

    2.1 promise的构造函数: new Promise(excutor)

    1. excutor函数:执行器,(resolve, reject) => {…}。该函数会在创建promise对象时立即同步调用,可以把异步操作放入此函数内部执行。
    2. resolve函数:将promise对象的状态变更为成功,并可以指定成功的结果值
    3. reject函数:将promise对象的状态变更为失败,并可以指定失败的结果值

    2.2 Promise.prototype.then: (onResolved, onRejeced)=>{}

    1. onResolved:promise对象状态为成功时的回调函数,(value)=>{},value为调用该then的promise对象的成功结果
    2. onRejeced:promise对象状态为失败时的回调函数,(reason)=>{},reason为调用该then的promise对象的失败结果

    2.3 Promise.prototype.catch: (onRejeced)=>{}

    1. onRejeced:promise对象状态为失败时的回调函数,(reason)=>{},reason为调用该catch的promise对象的失败结果

    2.4 Promise的静态方法

    1. Promise.resolve(value):返回一个成功状态的promise对象;
      (1)value不是promise类型数据:状态成功,结果就是value
      (2)value是promise类型的数据:直接返回value
    2. Promise.reject(value):返回一个失败状态的promise对象;
      (1)value不是promise类型数据:状态失败,结果就是value
      (2)value是promise类型的数据:状态失败,返回结果就是value
    3. Promise.all([p1,p2,p3]):返回一个新的promise对象;
      (1)p1,p2,p3是promise对象,当它们都成功时,all返回一个成功状态的promise对象,成功结果为p1,p2,p3的结果值组成的数组。
      (2)p1,p2,p3中任意一个失败后,all返回一个失败状态的promise对象,失败结果为失败的那个promise对象的失败值。
    4. Promise.race([p1,p2,p3]):返回一个新的promise对象;
      (1)p1,p2,p3中任意一个率先成功后,race返回一个成功状态的promise对象,成功结果为成功的那个promise对象的成功值。
      (2)p1,p2,p3中任意一个率先失败后,race返回一个失败状态的promise对象,失败结果为失败的那个promise对象的失败值。

    三、Promise的关键问题

    3.1 一个promise对象指定多个的回调时,都会调用吗?(不是指链式调用)

    答:都会调用

    let p =new Promise((resolve,reject)=>{
          reject('ok')
        })
        p.then(res=>{
          console.log(res,'111')
        },(err)=>{
          console.log(err,'333')
        })
        p.then(res=>{
          console.log(res,'222')
        },(err)=>{
          console.log(err,'444')
        })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    3.2 改变状态和指定回调函数的先后顺序

    注意:then()的作用就是指定回调函数,并等待promise对象改变时,执行指定的回调函数。

    1. 当在同步代码中执行resolve或reject时,先改变状态,后指定回调函数
    let p =new Promise((resolve,reject)=>{
          resolve('ok')
        })
        p.then(res=>{
    	  console.log(res)
        },(err)=>{
    	  console.log(err)
        })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    1. 当在异步代码中执行resolve或reject时,先指定回调函数,后改变状态
      let p =new Promise((resolve,reject)=>{
          setTimeout(() => {
            resolve('ok')
          }, 3000);
        })
        p.then(res=>{
    	  console.log(res)
        },(err)=>{
          console.log(err)
        })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3.3 then方法返回的promise对象受什么影响?

    前提:成功时调用onResolved, 失败时调用onRejeced

    1. 函数中没返回值:返回一个成功状态的promise,结果为undefined
    2. 函数中throw异常:返回一个失败状态的promise,结果为异常值
    3. 函数中返回了promise类型对象:取决于此对象状态和结果
    4. 函数中返回了非promise类对象:返回一个成功状态的promise,结果为该对象值

    四、Promise自定义封装

    五、async与await

    为了拿到promise对象的结果,以前需要使用then方法来拿到结果,现在可以使用async await 来直接拿到promise对象的结果。不在需要使用函数调用的方式,直接使用表达式即可。比链式调用更加方便直观
    then方式:

    const fs = require("fs");
    
    function read(url){
        return new Promise(function(resolve,reject){
            fs.readFile(`./${url}.txt`,function(err,data){
                if(err)return;
                resolve(data.toString());
            });
        });
    }
    read(1).then(function(data){
        console.log(data);
        read(2).then(function(data){
            console.log(data);
            read(3).then(function(data){
                console.log(data);
                read(4).then(function(data){
                    console.log(data);
                    read(5).then(function(data){
                        console.log(data);
                        read(6).then(function(data){
                            console.log(data);
                        });
                    });
                });
            });
        });
    });
    // 或者
    read(1).then(function(data){
        console.log(data);
        return read(2)
    }).then(function(data){
        console.log(data)
        return read(3)
    }).then(function(data){
        console.log(data)
        return read(4)
    }).then(function(data){
        console.log(data)
        return read(5)
    })
    
    • 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
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    async await方式

    async function main(){
        var data1 = await read(1);
        console.log(data1);
        var data2 = await read(2);
        console.log(data2);
        var data3 = await read(3);
        console.log(data3);
        var data4 = await read(4);
        console.log(data4);
        var data5 = await read(5);
        console.log(data5);
        var data6 = await read(6);
        console.log(data6);
    }
    main();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    5.1 async

    1. 函数的结果是一个promise对象
    2. 该对象的结果由async函数return的返回值决定

    5.2 await

    1. await 必须写在 async 函数中(es2022中top-level,await可以脱离async使用了), 但 async 函数中可以没有 await。
    2. 如果 await 的 promise 失败了, 会抛出异常, 需要通过 try…catch 捕获处理
  • 相关阅读:
    Vue组件的存放目录问题
    【星海出品】flask (四) 三方工具使用
    BiLSTM算法(一)
    王道数据结构二叉树算法大题代码总结
    Github上面的这个Nacos2.1多数据库集成适配项目真心不错:Nacos-MultiDataSource
    【AI】深度学习——前馈神经网络——卷积神经网络
    java基于微信小程序的社区心理健康咨询辅导服务系统 uniapp 小程序
    如何在 Chrome 中设置HTTP服务器?
    深度学习对 MRI 进行分类
    CPP 新语法规则笔记
  • 原文地址:https://blog.csdn.net/u010821983/article/details/126574240