TypeScript中的 async 的用法

typescript 中,异步函数 async 是一种特殊类型的函数,它可以返回一个 Promise 对象。异步函数使用 async 关键字声明,并使用 await 关键字等待 Promise 对象的完成。

typescript 中,异步函数 async 是一种特殊类型的函数,它可以返回一个 Promise 对象。异步函数使用 async 关键字声明,并使用 await 关键字等待 Promise 对象的完成。

下面详细记录一下 typescript 中的异步函数用法

什么是异步函数?

在 ts 中,如果使用 async function 定义一个函数,那么这个函数就是异步函数,这点和 python 很像

ts
function normal() {
  return 123;
}

async function asyncFn() {
  return 123;
}

什么是 Promise

Promise 是一个用于处理异步操作的对象,表示一个“未来才会有结果的值”。它有三种状态:

状态描述
pending等待中(未完成)
fulfilled已成功完成
rejected已失败

对于一个耗时的操作,如网络请求,本地 IO 操作,可以不阻塞整个进程

定义一个返回 Promise 对象的函数

ts
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);
  });
}

一般有两类结果

  1. 成功使用 resolve(xxx) 返回
  2. 失败使用 reject(xxx) 返回,这个 reject 的效果相当于抛了一个异常

也可以直接返回数据,如

ts
async function asyncFn() {
  return 123;
}

这种看似返回了 123, 但其实是返回的是 Promise<number>

ts
async function test() {
    return 123
}

const result = test();
console.log(result);

上面代码输出Promise { 123 }

普通函数也可以返回 Promise 对象

一个普通的 function 函数,也是可以返回一个 Promise 对象的

ts
function test2() {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(123)
        }, 1000);
    }
    );
}

如何调用 async 函数?

如果直接调用一个异步函数,无论是 async function 定义的,还是普通的 function 函数,但是返回的是 Promise 对象,都将会得到一个 Promise { <pending> }

ts
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();

上面的输出为

ts
t1 Promise { <pending> }
t2 Promise { 123 }
t3 Promise { <pending> }

并不能正常的得到函数运行的结果

如何获得异步的执行结果呢? 有以下几种方式

1、使用 await

使用 await

ts
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 一起使用

ts
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

这个是传统的写法

ts
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。

ts
function main() {
    (async()=>{
        try{
            const res1 = await asyncFn(false);
            console.log(res1)
        }catch(err){
            console.error(err)
        }   
    })();    
}

main();

无论那种方式,其实都是对于 Promise 对象结果的获取

杨彦星 后端工程师 · 序语程言主理人

做了八年后端,最近在 AI 行业折腾。喜欢把复杂的事情拆开讲清楚,讨厌「显而易见」这四个字。这里记录我踩过的坑和攒下的经验,愿你少踩一点。

yangyanxing1005@qq.com

查看主页