在上一篇博文中说到的Generator函数,虽然其配合Promise对象封装了异步操作,相比单纯的使用Promise简洁明了了,也大大增强了可维护性和可读性,但是有没有觉得它的一个特点比较的low,那就是需要手动操作执行异步操作.next()
,为此ES6又新推出一个函数,async函数,简单一句话来说就是Generator函数的语法糖。
基础示例代码
const fetch = url => {
return new Promise((resolve, reject) => {
setTimeout(url ? resolve : reject, 1000, url ? 'success' : 'failure');
}).catch(err => err)
}
const manageFetch = async function () {
const result1 = await fetch(true)
const result2 = await fetch(false)
const result3 = await fetch(true)
return {
result1,
result2,
result3,
}
}
manageFetch().then(data => {
console.log(data) // {result1: "success", result2: "failure", result3: "success"}
}).catch(err => {
console.log(err)
})
一、优势
1、内置执行器
这就意味着我们不需要手动的一句一句.next()
,而只要像其他函数一样,一句就ok,比如manageFetch()
。
2、更好的语义
async和await,比起星号和yield,语义更清楚了。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。
3、更广的适用性
async函数的await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即 resolved 的 Promise 对象)。
4、返回值是 Promise
async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then方法指定下一步的操作。
二、基本语法
async函数返回一个 Promise 对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的await语句。比如:上述基础示例代码
1、async返回Promise对象状态
只要async函数内部没有报错或内部子Promise状态没有reject就会返回resolve状态,关于其resolve函数的参数是其async函数的return值,若没有则为undefined;当状态为reject时,参数则为所抛异常或则其内部第一个状态为reject的子Promise中reject所传参数。
2、await语句
正常情况下,await命令后面是一个 Promise 对象,返回该对象的结果【也就是Promise对象中resolve函数或则reject函数所传的参数】。如果不是 Promise 对象,就直接返回对应的值。
三、错误机制处理
当async函数中的子Promise对象中存在一个状态为reject时,async函数就会被终止并使async所返回的Promise状态变为reject,参数为其内部子Promise对象第一个状态为reject所传的参数。
对于async函数的错误机制,在不同的场景我们有不同的处理手段。
1、假如存在三个没有依赖的请求,要求同时发送,其中某个抛出异常并不会影响其他的请求。
const fetch = url => {
return new Promise((resolve, reject) => {
setTimeout(url ? resolve : reject, 1000, url ? true : false);
})
}
const manageFetch = async function () {
const promise1 = fetch(true).catch(err => err)
const promise2 = fetch(false).catch(err => err)
const promise3 = fetch(true).catch(err => err)
const result = await Promise.all([promise1, promise2, promise3])
return result
}
manageFetch().then(data => {
console.log(data) // [true, false, true] 【一秒后打印】
})
注意:为了使async函数不会被可能的某个请求异常中断,我们必须为每个内部子Promise对象添加异常捕获。
2、当有三个请求存在依赖时,比如B请求依赖A请求的返回结果,C请求依赖B请求的返回结果。
const fetch = ({url = 'defaultValue'}) => {
return new Promise((resolve, reject) => {
setTimeout(url ? resolve : reject, 1000, url ? true : false);
})
}
const manageFetch = async function () {
const result1 = await fetch({url: true}).catch(err => err)
const result2 = await fetch({url: result1}).catch(err => err)
const result3 = await fetch({url: result2}).catch(err => err)
return result3
}
manageFetch().then(data => {
console.log(data) // true 【三秒后打印】
})
注意: 同上,因为防止依赖请求异常,所以我们就可以利用解构解析来设定url
初始值