众所周知,异步性是JavaScript的一项强大功能。许多可能长时间运行、或较为耗时的函数,能够返回Promise,而不会被阻止运行。
const url = 'https://the-one-api.dev/v2/book'
let prom = fetch(url)
prom // Promise {<pending>}
// wait a bit
prom // Promise {<fullfilled>: Response}, if no errors
// or
prom // Promise {<rejected>: Error message}, if any error
在上述代码段中,针对fetch的调用返回了一个状态为“待处理(pending)”的Promise。而当API返回响应时,它将会转换为“已实现(fulfilled)”的状态。
在Promises中,你可以执行如下操作,来通过API的调用,将响应解析成为JSON。
const url = 'https://the-one-api.dev/v2/book'
let prom = fetch(url)
prom // Promise {<fullfilled>: Response}
.then(res => res.json())
.then(json => console.log(json)) // prints response, if no errors
.catch(err => console.log(err)) // prints error message, if any error
2017年,JavaScript推出了两个新的关键字async和await,来使得Promises的处理和使用变得更加容易和流畅。当然,它们并非Promises的替代,只是Promises概念之上的语法增强。
而且,并非让所有的代码里都出现在一系列的“then”函数,await旨在让其更像同步的JavaScript。你可以使用带有await的try…catch,来代替直接使用Promise的catch函数去处理错误。下面是具有同等效果的await代码。
const url = 'https://the-one-api.dev/v2/book'
let res = await fetch(url) // Promise {<fullfilled>: Response} -await-> Response
try {
let json = await res.json()
console.log(json) // prints response, if no errors
} catch(err) {
console.log(err) // prints error message, if any error
}
当然,async关键字也有着“硬币的另一面”,它会将任何待发送的数据封装到一个Promise中。下面是一段旨在通过异步函数添加多个数字的程序代码。在现实情况中,您的代码可能会比它更加复杂。
async function sum(...nums) {
return nums.reduce((agg, val) => agg + val, 0)
}
sum(1, 2, 3) // Promise {<fulfilled>: 6}
.then(res => console.log(res) // prints 6
let res = await sum(1, 2, 3) // Promise {<fulfilled>: 6} -await-> 6
console.log(res) // prints 6