同步 / 异步
我个人认为 TypeScript 最大的优势之一是它在处理异步操作时的便捷和易上手。在这个部分中我将会详细介绍这两个非常有用的东西。首先我们要知道什么是同步和异步操作。
同步操作
同步操作
是指代码按照顺序执行,每一行代码都会等待上一行代码执行完毕后再执行。这种操作方式是最常见的,也是最容易理解的。其实就是我们平时写的代码,一行一行有序执行。这里就不再赘述。
异步操作
异步操作
是指代码不按照顺序执行,可以让多个操作同时进行。这样的操作可以避免程序进行等待。
一个简单的例子是当我们需要获取 小明 小红 小刚 的手机号时,我们需要分别在电话本中查找他们的号码。如果是同步操作,我们需要先找到小明的号码,再找到小红的号码,最后找到小刚的号码。这样的操作是非常耗时的。但是如果是异步操作,我们可以同时查找他们的号码,这样就会节省很多时间。
什么时候使用异步操作
异步操作固然节省了很多时间,但是切记,在数据有依赖关系的情况下,我们必须使用同步操作。比如我们需要获取小明的手机号,然后根据小明的手机号获取小明的地址。这时候我们就必须使用同步操作,因为小明的地址依赖于小明的手机号。
异步操作的实现
为了实现异步操作,我们需要介绍几个概念:async
、 await
以及 Promise
。这三个概念是 TypeScript 中处理异步操作的核心。
async
async
是一个修饰符,用来表示一个函数是异步的。举个例子,我们有一个函数 getPhone
,这个函数是异步的,我们可以这样定义这个函数:
在这个例子中,async
修饰符告诉 TypeScript 这个函数是异步执行的,当我们调用这个函数时,系统会在后台执行这个 getPhone
函数,然后不会等待 getPhone
函数执行完毕就会执行下一行代码。
Promise
现在你可能发现了一个问题,如果我们不执行 getPhone
函数,我们怎么知道这个函数会返回什么类型的值呢?在这种情况下,传统的 : number
类型注解就不再适用了。这时候我们就需要 Promise
。
Promise
是一个对象,用来表示一个异步操作的最终完成或者失败。我们可以简单理解为 Promise
是一个空盒子,你可以通过轮廓知道这个盒子里面有什么类型的东西,但是这个轮廓里有可能是空的。
听起来有点绕?没关系,我们来修改一下上面的例子:
现在,我们给 getPhone
函数添加了一个返回类型 Promise<string>
,表示这个函数会返回一个 string
类型的值。
await
当然,有时候我们的异步操作是有依赖关系的,这时候我们就需要使用 await
关键字。await
关键字可以让 TypeScript 等待一个异步操作的结果。换句话说,await
可以把一个异步操作变成一个同步操作。在这里,我们新增了一个函数 getAddress
,这个函数需要输入一个电话号码,然后返回一个地址:
现在我们可以使用 await
关键字来等待 getPhone
函数的返回值:
在这个例子中,我们先等待 getPhone
函数完整执行完毕,然后把它的结果存入 phone
变量中。接着我们再等待 getAddress
函数完整执行完毕,然后把它的结果存入 address
变量中。最后我们打印出 address
变量的值。