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

Promise的实例方法

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

then()

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

在使用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的调用。

相关推荐
Jmyd01235 小时前
Web端3D营销展厅技术实现路径:从素材上云到线索回流的数据链路
前端·3d·性能优化·三维数字化
半个落月5 小时前
LangChain Agent 中间件实战(上):生命周期、状态、短路与工具包
javascript·langchain
砚凝霜5 小时前
【软考信息安全】第二十二章 Web服务器安全分析与增强——Apache与IIS
服务器·前端·安全
半个落月5 小时前
LangChain Agent 中间件实战(下):DeepAgents文件权限、长期记忆与对话摘要
javascript·langchain
u0111026757 小时前
JPG、PNG、WebP 怎么选?按透明度、体积和使用场景做判断
前端·javascript·vue.js·图像处理·ai作画
jerrywus8 小时前
让 AI 写完代码后交一份报告:我改造了 answer-me-with-html
前端·claude·cursor
派小心.8 小时前
小程序分享链路中来源参数的传递校验
大数据·前端·数据库·人工智能·小程序·数据分析
hhb_6189 小时前
一键生成数据看板,ECharts实战演示
前端·javascript·echarts
Java后端的Ai之路9 小时前
08_React组件API
前端·react.js·前端框架
小马不起床9 小时前
零基础玩转 FastAPI_09:前端基础工程构建
前端·状态模式·fastapi