Promise是ECMAScript6中异步编程的解决方案,async和await是ECMAScript8中引入的针对Promise异步编程的进一步优化,让异步编程的写法完全和同步编程一样,写出来的代码即美观,优雅,又易读。如果你还不懂Promise的使用,建议先去学习一下promise,再来看这篇文章。
下面这段代码定义了一个login函数和一个fetchUserInfo函数,在onClickLogin中调用login获取token,然后调用fetchUserInfo获取用户信息,模拟我们常见的登陆过程。
/**
* 登陆,返回token
* @returns
*/
function login(): Promise<string> {
return new Promise((resolve, reject) => {
//这里可以执行一些耗时的异步任务,比如网络请求
//IO操作等,我们使用setTimeout来模拟
setTimeout(() => {
const random = Math.random() * 10
if (random < 5) {
resolve("ed87y65t03qczvgtw6538ikplon33u")
} else {
reject(new Error("login error"))
}
}, 500);
})
}
interface User {
name: string;
age: number;
}
/**
* 传入token获取用户信息
*/
function fetchUserInfo(token: string): Promise<User> {
return new Promise<User>((resolve, reject) => {
setTimeout(() => {
if (token) {
resolve({ name: "zhang", age: 28 })
} else {
reject(new Error("fetchUserInfo error"))
}
}, 800);
})
}
function onClickLogin() {
login().then(result => {
return fetchUserInfo(result)
}).then(result => {
console.log(JSON.stringify(result));
}).catch(error => {
console.error(error.message)
})
}
onClickLogin()
下面我们可以用async,await对调用过程做进一步的优化
async function onClickLogin() {
try {
const token = await login()
const user = await fetchUserInfo(token)
console.log(JSON.stringify(user));
} catch (error) {
console.error(error.message)
}
}
优化后的代码和同步代码的写法看起来完全一致,可读性很强,await就像它的字面意义一样,需要等待一下才能获取 结果,在等待的过程先去干其它事情,等到结果返回了再来执行后面的任务。
下面总结一下async,await的用法:
1、如果一个函数返回值为Promise,那么可以用await进行优化
2、如果一个函数内部存在await调用,那么这个函数一定要用async修饰
3、async修饰的函数返回值一定只能是Promise
async function onClickLogin(): Promise<boolean> {
try {
const token = await login()
const user = await fetchUserInfo(token)
console.log(JSON.stringify(user));
return true
} catch (error) {
console.error(error.message)
return false
}
}
我们看上面的代码,如果我们希望将登陆成功失败的结果以boolean值返回回去,onClickLogin的返回值必须是Promise,不能是boolean,并且我们发现,async修饰的函数return语句可以省略Promise,直接return true或者false就行