Promise(下)


对于实例方法then()catch(),需要清楚的是,会返回一个新的Promise对象
同一个Promise对象,可以绑定多个回调,但链式使用then()时,并不是一直操作一个对象,而是不断返回的新对象

const p = new Promise((resolve,reject) => {  
  resolve(10)  
})  
p.then(value => {  
  console.log("一号回调")  
  console.log(value)// 10  
  return 20  
})  
p.then(value => {  
  console.log("二号回调")  
  console.log(value)// 10  
  return 20  
}).then(value => {  
  console.log(value)// 20  
})

执行顺序是正常的从上至下,对一个对象绑定多个回调的情况很少,通常以链式调用为主

then()返回的是非Promise对象时,将此返回值当作返回的Promise对象的结果,状态为fulilled;如果返回了一个Promise对象,那么它就是返回值
catch()同样遵循此规则,也就是说,catch()后续可以继续接着then(),源源不断…

函数执行过程中出现错误,同样按照失败来处理

如果细看then()catch(),这和trycatch没有多大差别,差一个常被遗忘的成员finallyPromise也提供了这个实例方法,就是使用的非常少,此处便不再细说

静态方法

实例对象的方法和属性都是属于短小精悍的存在,除此之外,Promise还有一些静态方法

all()
  • 接收一个数组,返回Promise对象。根据数组成员的状态,决定Promise状态与结果
  • 对于数组成员
    • Promise对象,则转换为成功状态Promise对象,当前成员作为成功结果
    • Promise对象,以其自身表现为主
  • 当所有成员进入了成功状态,那么返回对象进入成功状态,将所有成员的成功结果包裹为数组,作为自己的成功结果
  • 如果有一个成员失败了,那么返回对象进入失败状态,其失败原因,为第一个失败的成员的失败原因,其他成员不会停止执行
Promise.all([  
  new Promise((resolve) => {  
    resolve(10);  
  }),  
  new Promise((resolve) => {  
    resolve(20);  
  }),  
]).then((values) => {  
  console.log(values); // [10, 20]  
});
allSettled()
  • all()不同于,如果出现失败的成员,不会导致返回对象的失败,而是等到所有成员都执行完毕之后,再返回
  • 因为可能出现失败的Promise对象,此时返回的结果会多一层包装。与all()相比,不追求全部成功,而是结果
    class Result {
      //状态
      status: "fulfilled" | "rejected"
      //成功的结果
      value?: any
      //失败的原因
      reason?: any
    }
    
race()
  • 参数形式与all()一致,不同的是,只关注第一个完成的成员
  • 第一个完成成员,将作为此方法的返回值,如同比赛一般
Promise.race([  
  new Promise((resolve, reject) => {  
    setTimeout(() => resolve(10), 100)  
  }),  
  new Promise((resolve, reject) => {  
    setTimeout(() => resolve(20), 200)  
 })  
]).then((value) => {  
  console.log(value) // 10  
})
any()
  • race()相仿,只关注第一个完成的成员,但关注的是成功,而非失败
  • 当第一个成员结束是成功时,表现与race()一致;只有当所有的成员都进入了失败状态,返回对象才进入失败状态,并且不会提供成员的失败原因
  • 更适合获取一组请求当中,第一个成功的结果,当然,也丢失了所有的失败原因
Promise.any([  
  new Promise((resolve, reject) => {  
    setTimeout(() => reject(10), 1000)  
  }),  
  new Promise((resolve, reject) => {  
    setTimeout(() => resolve(20), 2000)  
  })  
]).then((value) => {  
  console.log(value) // 20  
})
resolve() & reject()
  • 快速生成对应的Promise()实例
Promise.resolve(10).then((value) => {  
  console.log(value) // 10  
})  
Promise.reject("失败了").catch((err) => {  
  console.log(err) //失败了  
})

async与await

还有两个特殊的关键词,asyncawait,很有趣的两个小玩意

async

async,直译就是异步,使用在函数上,如同classpublic一般,给一个函数打上异步记号

//函数声明,需要加在function的前面
async function asyncFn1() {  
 return 10  
}  
//函数表达式同理,此处是箭头函数省略function罢了
const asyncFn2 = async () => {  
 return 20  
}

当一个函数被打上了async记号之后,它便不是它自己了吗?当然不是,此处会产生的变化是在返回值上,让函数表现的如同then()一样,将返回值包装成一个Promise对象。恩对,就这点

async

再说await,它就不能单独使用了,只能在标记了async的函数当中去使用
遵循这一条之后,再说表现,如同直译,等待,等谁下课呢,一个对象…

(async () => {  
  const result = await new Promise((resolve => {  
    setTimeout(() => {  
      console.log("发回响应")
      resolve("成功结果")  
    }, 2000)  
  }))  
  console.log(result)// 2s之后输出 "成功的结果"
})()

需要注意的是,输出的顺序可是从上至下,如同同步顺序一般执行,这就是await,等待右侧Promise做出改变之后,将结果交给左边
若是执行过程中失败或者出现错误,那么async就会进入失败状态,并且跳出执行,如同手动抛出了错误,可以由catch捕获

(async () => {  
  try {  
    const result1 = await new Promise(((resolve, reject) => {  
      console.log("开始执行一号任务")
      setTimeout(() => {  
        reject("失败啦")  
      }, 2000)  
    }))  
    const result2 = await new Promise(((resolve, reject) => {  
      console.log("开始执行二号任务")
      setTimeout(() => {  
        reject("失败啦")  
      }, 2000)  
    })) 
    console.log(result)  
  } catch (e) {  
    console.log(e)  
  }  
})()
结合使用

在两个标记的加持下,便获得神奇的能力,伪同步执行代码
可以以同步思维来写异步代码,由await等待结果,不必想什么回调、异步结果时机、错误,都能统一处理,其流程也是符合正常的阅读习惯,从上至下

这都是属于是Promise的手段,asyncawait只是语法糖

现在再回看之前写的读取文件示例,可以这样改

const fs = require("fs/promises")

const readFile = async () => {  
    const data1 = await fs.readFile("./doc/1.log", "utf-8")  
    const data2 = await fs.readFile("./doc/2.log", "utf-8")  
    const data3 = await fs.readFile("./doc/3.log", "utf-8")  
    return [data1, data2, data3]  
}  
readFile().then((value) => {  
  console.log(value)  
}).catch((err) => {  
  console.log(err)  
  console.log("外层捕获到错误")  
})

很重要的一点是,async函数的返回值是Promise对象,这一点是不变的,部分框架、插件提供hook函数并不支持此类返回值,如vue3setup()ReactuseEffect()

最后

没有Promise,很多事情一样能做,而有了Promise,能让过程、结果、错误处理,在总体上条理清晰

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值