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

相关推荐
普通码农3 小时前
uniapp开发微信小程序使用takeSnapshot截图保存分享
前端
snows_l4 小时前
MacOS 通过Homebrew 安装nvm
前端·macos
前端开发爱好者4 小时前
下一代全栈框架:Deno + Vite 的结合体!
前端·javascript·后端
CUGGZ4 小时前
前端部署,又有新花样?
前端·javascript
Zz_waiting.4 小时前
Javaweb 14.4 Vue3 视图渲染技术
前端·javascript·vue.js
前端开发爱好者4 小时前
一键 i18n 国际化神库!适配 Vue、React!
前端·javascript·vue.js
前端开发爱好者4 小时前
Vite 移动端调试利器!开发效率飙升 300%!
前端·javascript·vue.js
BillKu5 小时前
容器元素的滚动条回到顶部
前端·javascript·vue.js
weixin_423391935 小时前
React 19 全面解析:颠覆性的新特性与实战指南
前端·javascript·react.js