promise 和 async / await

同步,异步

同步和异步是在计算机程序中用于描述执行任务时的两种不同方式。

同步执行指的是任务按顺序一个接一个地执行,每个任务完成之后才能进行下一个任务。这就意味着在执行一个任务时,程序会一直等待该任务完成之后再去执行下一个任务。

异步执行指的是任务并不是按照顺序一个接一个地执行的,而是可以同时执行多个任务,并且在等待某个任务执行完成时,程序仍然可以继续执行其他任务。

异步操作并不一定计算量大或要等很长时间。只要你不想为 等待某个异步操作而阻塞线程执行,那么任何时候都可以使用。

JavaScript 采用事件循环(Event Loop)的机制来实现异步操作。
事件循环是一个持续运行的过程,它会从消息队列中取出消息,并将其分配给相应的事件处理程序来处理。
在 JavaScript 中,一些操作(如定时器、网络请求等)会被放入消息队列中,当它们完成时,就会添加到消息队列的末尾。
复制代码

promise

premise是es6新增的引用类型,是 JS 中进行异步编程的新解决方案。通过new操作符实例化

三种状态

  • 待定(pending)
  • 兑现(fulfilled / “解决” resolved)
  • 拒绝(rejected)

promise 状态的改变

  1. pending 变为 fulfilled
  2. pending 变为 rejected

说明: 只有这 2 种, 且一个 promise 对象只能改变一次 无论变为成功还是失败, 都会有一个结果数据 成功的结果数据一般称为 value, 失败的结果数据一般称为 reason,当状态转换为兑现/拒绝 时,promise的状态就不再改变。

Promise.resolve

调用Promise.resolve,可以实例化一个兑现(fulfilled)的promise

let p1 =  Promise.resolve(3)
// 多余的参数会省略
let p2 = Promise.resolve(4,5,6)
console.log(p1)// Promise<resolved>:3
console.log(p2)// Promise<resolved>:4
// 传入错误的对象也会转为解决的promise
let p3 = Promise.resolve(new Error('err'))// Promise<resolved>:Error
console.log(p3)
复制代码

Promise.reject

Promise.reject()会实例化一个拒绝的promise并抛出一个异步错误(这个错误不能被try/catch捕获,只能通过拒绝处理程序捕获)

let p1 =  Promise.reject(3)
let p2 = Promise.reject(4,5,6)
console.log(p1)
p1.catch(err => console.log('catch捕获:'+err))
console.log(p2)
p2.catch(err => console.log('catch捕获:'+err))
let p3 = Promise.reject(Promise.resolve(3))
console.log(p3)
p3.catch(err => console.log('catch捕获:'+err))
复制代码

Promise.prototype.then()

Promise.prototype.then()是为promise实例添加处理程序的主要方法。接受两个参数:onResolved处理程序和onRejected处理程序,分别在promise进入“兑现”和“拒绝”状态执行

let p1 = new Promise((resolve,reject) => {
// setTimeout 属于宏任务
setTimeout(resolve('成功'),1000)
console.log('进入Promise1函数体')
})
// promise.then属于微任务
p1.then((res) => { console.log('resolve:'+res) },(rej) => {console.log('reject:'+rej) })
let p2 = new Promise((resolve,reject) => {
// setTimeout 属于宏任务
setTimeout(reject('失败'),1000)
console.log('进入Promise2函数体')
})
// promise.then属于微任务
p2.then((res) => { console.log('resolve:'+res) },(rej) => {console.log('reject:'+rej) })
复制代码

Promise.prototype.catch()

Promise.prototype.catch()方法用于给promise添加拒绝处理程序。只接收一个参数:onRejected处理程序。(相当于调用Promise.prototype.then(null,onRejected))

let p1 = new Promise((resolve,reject) => {
// setTimeout 属于宏任务
setTimeout(reject('捕获失败'),1000)
console.log('进入Promise1函数体')
})
p1.catch(err => console.log(err))
复制代码

Promise.prototype.finally()

Promise.prototype.finally()方法用于给promise添加onFinally处理程序,这个处理程序在promise状态改变时触发。

let p1 = new Promise((resolve,reject) => {
// setTimeout 属于宏任务
setTimeout(resolve('成功'),1000)
console.log('进入Promise1函数体')
})
p1.finally(() => { console.log('执行了:finally') })
let p2 = new Promise((resolve,reject) => {
// setTimeout 属于宏任务
setTimeout(reject('失败'),1000)
console.log('进入Promise2函数体')
})
p2.finally(() => { console.log('执行了:finally') })
复制代码

Promise.all / Promise.race

Promise类提供两个将多个promise实例组合成一个实例的静态方法:Promise.all / Promise.race,合成后的状态取决于内部promise的行为

  • Promise.all()

Promise.all()方法它接收一个由Promise对象组成的数组作为参数,并返回一个新的Promise对象。创建的promise会在内部promise全部解决之后再解决或在数组中任何一个Promise被拒绝(rejected)时被拒绝,并传递该Promise的拒因给新的Promise对象。这个方法接收一个可迭代对象,返回一个新promise

const promises = [ 
fetch('https://api.example.com/data1'),
fetch('https://api.example.com/data2'), 
fetch('https://api.example.com/data3')
]; 
Promise.all(promises) 
.then(results => { // 处理所有Promise对象的结果 console.log(results[0]); console.log(results[1]); console.log(results[2]); }) 
.catch(error => { // 处理Promise对象拒绝的情况 console.error(error); });
复制代码
  • Promise.race()

Promise.race()方法返回一个包装后的promise,是一组集合中最先解决或拒绝的promise的镜像(返回第一个被处理的结果)。

let p1 = new Promise((resolve,reject) =>{
    setTimeout(reject('失败1'),1000)
})
let p2 = new Promise((resolve,reject) =>{
    setTimeout(resolve('成功1'),1000)
})
let p3 = new Promise((resolve,reject) =>{
    setTimeout(reject('失败2'),1000)
})
let p4 = new Promise((resolve,reject) =>{
    setTimeout(resolve('成功1'),1000)
})
Promise.race([p1,p2,p3,p4])
.then(res => console.log(res))
.catch(err => console.log(err))
复制代码

async/await

async关键字用于声明异步函数,可以用在函数声明,函数表达式,箭头函数和方法上

async function foo(){ }
let bar = async function(){ }
let baz = async foo() => { }
class Qux {
    async qux(){  }
}
复制代码

使用async关键字可以让函数具有异步特征,但总体上其代码仍然是同步求值

async function foo(){
    console.log(1)
}
foo()
console.log(2)
// 1 , 2
复制代码

当使用return 关键字 / throw 关键字

// 使用 return 关键字
async function foo(){
    console.log(1)
    return '成功'
}
foo().then(console.log).catch(console.log)
console.log(foo())

// 使用 throw 抛出错误
async function foo(){
    console.log(1)
    throw '失败'
}
foo().then(console.log).catch(console.log)
console.log(foo())
复制代码

await关键字可以暂停异步函数代码的执行,直到异步函数返回结果后再继续执行下面的代码。await关键字必须在异步函数中(async)使用

async function myFunc() {
    // 同步执行
    console.log('before await');
    let res = await new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve('成功') },3000) })
    // 3秒后执行
    console.log('after await');
    console.log(res)
}
myFunc()
复制代码

// promise 返回失败结果 需要配合try catch使用
async function myFunc() {
    try{   
        console.log('before await');
        let res =  await new Promise((resolve,reject)=>{ setTimeout(()=>{ reject('失败') },3000) })
        console.log('after await');
        console.log(res)
    }catch(err){
        console.log(err)
    }
}
 myFunc()
复制代码

async/await 对于 promise的优势

  1. 代码更简洁易懂
  2. 错误处理更加直观(使用try/catch)
  3. 可读性更好

虽然 async/await 在代码书写上更加简洁易懂,但它本质上还是基于 Promise 实现的,因此在性能上与 Promise 并不存在太大差异。 它也需要在现代浏览器或 Node.js 环境中使用,对于老旧浏览器还是需要使用 Promise 等技术实现异步编程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chickenFast

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值