Promise实例方法和async、await语法糖

Promise的实例方法

promise为我们提供了三个实例方法,then、catch、finally。这三个实例方法可以帮助我们在promise状态改变时便捷地进行处理。在开发过程中了解这三个实例方法的具体实现可以帮助我们更好的进行

then()

then方法在使用时我们需要最多编写两个形参,onFulfilledonRejected,但由于这两个参数是互斥情况,所以至多只会有一个形参生效。

在使用then()之前,我们需要知道如何处理then()的参数和返回值。

参数:

onFulfilled: onFulfilled应该编写为一个回调函数形式,用于处理resolve()或上一个then()返回的参数。 如果onFulfilled不是一个函数,在编译时会自动替换为(x) => x。

onRejected: onRejected()应该编写为一个回调函数形式,用于处理reject()或上一个then()返回的参数。如果onFulfilled不是一个函数,在编译时会自动替换为(x) => {throw x}。

返回值:

then方法在调用时会立即返回一个新的promise,且该promise的状态为padding,直到onFulfilled或onRejected对其进行处理。

示例:

javascript 复制代码
const p1 = new Promise((resolve, rejected) => {
    resolve("成功")
})

const p2 = new Promise((resolve, rejected) => {
    rejected("失败")
})

const p3 = new Promise((resolve, rejected) => {
    resolve(new Promise(resolve => resolve("new Promise 成功")))
})

const p4 = new Promise((resolve, rejected) => {
    rejected(new Promise(resolve => resolve("new Promise 成功")))
})

p1.then((val) => {console.log("p1 " + val)}, (val) => {console.log("p1 " + val)})

p2.then((val) => {console.log("p2 " + val)}, (val) => {console.log("p2 " + val)})

p3.then((val) => {console.log("p3 " + val)}, (val) => {console.log("p3 " + val)})

p4.then((val) => {console.log("p4 " + val)}, (val) => {console.log("p4 " + val)})

返回值

shell 复制代码
> "p1 成功"
> "p2 失败"
> "p4 [object Promise]"
> "p3 new Promise 成功"

由于then是异步调用且涉及到入参的解析封装再处理,所以多个promise在调用then方法时返回顺序并不一定按照调用顺序。

catch()

catch方法是对then方法的一个封装,它实际上是调用then(undefined, onRejected)来进行错误处理。由于onFulfilled处写入的undefined,所以catch无法只能处理onRejected事件。

参数:

onRejected: onRejected()应该编写为一个回调函数形式,用于处理reject()或上一个then()传入的reason。如果onFulfilled不是一个函数,在编译时会自动替换为(x) => {throw x}。

返回值:

返回一个新的promise,这个promise状态是padding,等待onRejected被调用。当onRejected被调用后会根据此次调用返回的reason进行处理。

javascript 复制代码
const p1 = new Promise((resolve, rejected) => {
    rejected('p1 error')
}).catch((reason) => {console.log('p1 ' + reason)})

const p2 = new Promise((resolve, rejected) => {
    throw new Error('error');
}).catch((reason) => {console.log('p2 ' + reason)})

const p3 = new Promise((resolve, rejected) => {
    resolve('error')
    throw new Error('error');
}).catch((reason) => {console.log('p3 ' + reason)})

const p4 = new Promise((resolve, rejected) => {
    setTimeout((resolve, rejected) => {
    rejected('error')
}, 1000)
}).catch((reason) => {console.log('p4 ' + reason)})

返回值:

javascript 复制代码
> "p1 p1 error"
> "p2 Error: error"
// p3因为是在resolve之后抛出的错误所以catch不会进行处理
// p4是在异步函数内部抛出的错误,catch没能成功捕获。

catch()能够对promise被拒绝时抛出的reason或报错进行处理,但是要注意异步函数内部抛出的错误以及resolve()之后抛出的错误无法捕获。

finally

catch相似,finally实际上也是在内部调用then方法then(onFinally, onFinally)。 但是在创建finally方法时只需要传入一个回调函数作为形参,不用强制传入两个形参。 onFinally不接受任何参数,调用时不用关心promise的拒绝原因或兑现值。所以通常用于 状态管理。

finally通常不会修改原promise的状态,但在onFinally回调函数中抛出错误时,原promise状态 也会被拒绝。

示例:

javascript 复制代码
let isLoading = false;

fetch(request) //模拟一个fetch请求
  isLoading=ture //状态转换发起请求
  .then((response) => {
     return response.json();
  })
  .then((json) => {
    console.log(json);
  })
  .catch((error) => {
    console.error(error); 
  })
  .finally(() => {
    // 请求结束状态置为false
    isLoading = false;
});

async和await

async和await是ES8增加的新特性,是promise的语法糖,使用async和await我们可以更好的对异步函数进行编写。

async

async通过结合function关键字便捷定义一个异步函数。 格式: async funcion。

每次调用异步函数时,都会返回一个新的 Promise 对象, 该对象将会被解决为异步函数的返回值,或者被拒绝为异步函数中未捕获的异常。 如果手动返回一个非promise对象,那么函数会在内部进行隐式封装使其为promise对象返回。

如果函数体内没有await关键字,那么该函数实则是同步执行。只有存在await关键字,该函数才会异步执行。

await

await操作符用于等待一个promise对象状态由padding转为onFulfilled或onRejected, 并获取其返回值。它只能在异步函数或顶层代码块里使用,在该promise状态转换前该函数不会往下执行。

await会获取从 Promise 实例或 thenable 对象取得的处理结果。 如果等待的值不符合 thenable,则返回表达式本身的值。

如果Promise返回一个rejected处理的结果,await会把拒绝的reason抛出。

示例

javascript 复制代码
async function foo() {
 	const result1 = new Promise((resolve, reject) => {
      console.log("this 1");
      setTimeout(() => {resolve(1)}, 1000);
    }).then(val => console.log(val))
    
    const result2 = new Promise((resolve, reject) => {
      console.log("this 2");
      setTimeout(() => {resolve(2)}, 500);
    }).then(val => console.log(val))
}

async function foo2() {
 	const result3 = await new Promise((resolve, reject) => {
      console.log("this 3");
      setTimeout(() => {resolve(3)}, 1000);
    }).then(val => console.log(val))
    
    const result4 = await new Promise((resolve, reject) => {
      console.log("this 4");
      setTimeout(() => {resolve(4)}, 500);
    }).then(val => console.log(val))
}

foo();
foo2();

返回值:

shell 复制代码
> "this 1"
> "this 2"
> "this 3"
> 2
> 1
> 3
> "this 4"
> 4

这个实例可以看出虽然foo和foo2都用async进行修饰,但是foo2()函数体内没有await关键字 两个promise依然是以状态变化的先后顺序来进行then方法的调用。

foo()函数体内由于用了await修饰,待result3完全执行完后再进行result4的调用。

相关推荐
We་ct1 天前
LeetCode 30. 串联所有单词的子串:从暴力到高效,滑动窗口优化详解
前端·算法·leetcode·typescript
木卫二号Coding1 天前
Docker-构建自己的Web-Linux系统-Ubuntu:22.04
linux·前端·docker
CHU7290351 天前
一番赏盲盒抽卡机小程序:解锁惊喜体验与社交乐趣的多元功能设计
前端·小程序·php
RFCEO1 天前
前端编程 课程十二、:CSS 基础应用 Flex 布局
前端·css·flex 布局·css3原生自带的布局模块·flexible box·弹性盒布局·垂直居中困难
天若有情6731 天前
XiangJsonCraft v1.2.0重大更新解读:本地配置优先+全量容错,JSON解耦开发体验再升级
前端·javascript·npm·json·xiangjsoncraft
2501_944525541 天前
Flutter for OpenHarmony 个人理财管理App实战 - 预算详情页面
android·开发语言·前端·javascript·flutter·ecmascript
打小就很皮...1 天前
《在 React/Vue 项目中引入 Supademo 实现交互式新手指引》
前端·supademo·新手指引
C澒1 天前
系统初始化成功率下降排查实践
前端·安全·运维开发
摘星编程1 天前
React Native + OpenHarmony:自定义useFormik表单处理
javascript·react native·react.js
C澒1 天前
面单打印服务的监控检查事项
前端·后端·安全·运维开发·交通物流