TypeScript中的 async 的用法
typescript 中,异步函数 async 是一种特殊类型的函数,它可以返回一个 Promise 对象。异步函数使用 async 关键字声明,并使用 await 关键字等待 Promise 对象的完成。
下面详细记录一下 typescript 中的异步函数用法
什么是异步函数?
在 ts 中,如果使用 async function 定义一个函数,那么这个函数就是异步函数,这点和 python 很像
| function normal() {
return 123;
}
async function asyncFn() {
return 123;
}
|
什么是 Promise
Promise
是一个用于**处理异步操作的对象**,表示一个“未来才会有结果的值”。它有三种状态:
状态 |
描述 |
pending |
等待中(未完成) |
fulfilled |
已成功完成 |
rejected |
已失败 |
对于一个耗时的操作,如网络请求,本地 IO 操作,可以不阻塞整个进程
定义一个返回 Promise 对象的函数
| async function asyncFn(r:boolean=true): Promise<string> {
return new Promise((resolve, reject) => {
setTimeout(() => {
if(r){
resolve('Async Function Result');
}else{
reject('Error occurred in Async Function');
}
}, 1000);
});
}
|
一般有两类结果
- 成功使用 resolve(xxx) 返回
- 失败使用 reject(xxx) 返回,这个 reject 的效果相当于抛了一个异常
也可以直接返回数据,如
| async function asyncFn() {
return 123;
}
|
这种看似返回了 123, 但其实是返回的是 Promise
| async function test() {
return 123
}
const result = test();
console.log(result);
|
上面代码输出Promise { 123 }
普通函数也可以返回 Promise 对象
一个普通的 function 函数,也是可以返回一个 Promise 对象的
| function test2() {
return new Promise((resolve) => {
setTimeout(() => {
resolve(123)
}, 1000);
}
);
}
|
如何调用 async 函数?
如果直接调用一个异步函数,无论是 async function 定义的,还是普通的 function 函数,但是返回的是 Promise 对象,都将会得到一个 Promise { <pending> }
| async function asyncFn(r:boolean=true): Promise<string> {
return new Promise((resolve, reject) => {
setTimeout(() => {
if(r){
resolve('Async Function Result');
}else{
reject('Error occurred in Async Function');
}
}, 1000);
});
}
async function test() {
return 123
}
function test2() {
return new Promise((resolve) => {
setTimeout(() => {
resolve(123)
}, 1000);
}
);
}
async function main() {
const t1 = asyncFn()
const t2 = test()
const t3 = test2()
console.log('t1', t1)
console.log('t2', t2)
console.log('t3', t3)
}
main();
|
上面的输出为
| t1 Promise { <pending> }
t2 Promise { 123 }
t3 Promise { <pending> }
|
并不能正常的得到函数运行的结果
如何获得异步的执行结果呢? 有以下几种方式
1、使用 await
使用 await
| async function main() {
const t1 = await asyncFn()
const t2 = await test()
const t3 = await test2()
console.log('t1', t1)
console.log('t2', t2)
console.log('t3', t3)
}
|
await 需要在 async function 函数中
使用 await 方式调用异步函数时,如果 Promise 返回的是 reject,则会报错,相当于其他语言里的 exception,所以经常配合 try 一起使用
| async function asyncFn(r:boolean=true): Promise<string> {
return new Promise((resolve, reject) => {
setTimeout(() => {
if(r){
resolve('Async Function Result');
}else{
reject('Error occurred in Async Function');
}
}, 1000);
});
}
async function main() {
try{
const r = await asyncFn(false);
console.log(r);
}catch(e){
console.error(e);
}
}
main()
|
2、使用 .then .catch
这个是传统的写法
| async function main() {
asyncFn(false).then(result=>{
console.log('Result:', result);
}).catch(error=>{
console.error('Caught Error:', error);
});
// 下面的代码并不需要等待上面的代码执行结束再执行
test2().then(result=>{
console.log('Test2 Result:', result);
});
}
|
使用 then 的方式,可以不必写在 async 函数里。
3、使用一个匿名的 async 调用
因为使用 await 需要在 async 函数中调用,所以这会引出一系列的问题,将原本不是 async 的函数改为 async ,那么整个函数调用链都需要修改,下面这种提供了一中匿名调用,依然使用 await ,但是不用写在 async 函数里
在不能使用 await
的地方(比如普通函数或全局作用域),通过创建一个临时 async 函数来使用 await
。
| function main() {
(async()=>{
try{
const res1 = await asyncFn(false);
console.log(res1)
}catch(err){
console.error(err)
}
})();
}
main();
|
无论那种方式,其实都是对于 Promise 对象结果的获取