Promise梳理

文章目录

  • 一、Promise简单介绍与基本使用
      • 1.1 Promise是什么?
      • 1.2 为什么要使用Promise?
        • 1.2.1 指定回调函数的方式更加灵活
        • 1.2.2 支持链式调用,可以解决回调地狱问题
      • 1.3 Promise的状态改变
        • 1.3.1 PromiseState
        • 1.3.2 PromiseResult
        • 1.3.3 Promise的工作流程
  • 二、Promise的API
      • 2.1 promise的构造函数: new Promise(excutor)
      • 2.2 Promise.prototype.then: (onResolved, onRejeced)=>{}
      • 2.3 Promise.prototype.catch: (onRejeced)=>{}
      • 2.4 Promise的静态方法
  • 三、Promise的关键问题
      • 3.1 一个promise对象指定多个的回调时,都会调用吗?(不是指链式调用)
      • 3.2 改变状态和指定回调函数的先后顺序
      • 3.3 then方法返回的promise对象受什么影响?
  • 四、Promise自定义封装
  • 五、async与await
    • 5.1 async
    • 5.2 await

一、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. 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.2 支持链式调用,可以解决回调地狱问题
  1. 什么是回调地狱? 回调函数嵌套调用,外部回调函数执行的结果是嵌套函数执行的条件
    Promise梳理_第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梳理_第2张图片

二、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')
    })

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. 当在异步代码中执行resolve或reject时,先指定回调函数,后改变状态
  let p =new Promise((resolve,reject)=>{
      setTimeout(() => {
        resolve('ok')
      }, 3000);
    })
    p.then(res=>{
	  console.log(res)
    },(err)=>{
      console.log(err)
    })

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)
})

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();

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 捕获处理

你可能感兴趣的:(javascript,javascript,前端,开发语言)