Anders Hejlsberg解释async/await设计理念:编译器自动处理状态机
为什么这么多语言从C#复制了async/await?安德斯·海尔斯伯格(@ahejlsberg)——TypeScript、C#和Turbo Pascal的创造者——谈他们设计中做对的地方:
#1 - async/await旨在解决事件循环模型中的一个常见问题:
“很多语言围绕协作式多任务构建,即它们有一个事件循环来调度事件。然后你处理事件,再返回到事件处理循环。这一切都在单线程中协作运行。
这样做的问题是,如果你要进行一些长时间运行的工作:如何在这段长时间运行的工作中间停止并协作地返回到事件循环?然后当我的结果准备好时,我可以回来继续执行。”
#2 - 状态机是解决方案,但难以构建:
“要在那种反转架构中做到这一点,你必须构建一个状态机。
状态机对人类来说出了名地难以实现,因为你必须将所有状态从堆栈移到对象中。然后你有一个大的case语句包裹你的整个逻辑。要理清思路简直是个噩梦。
但是,从串行执行代码到状态机的转换,即延续传递风格的转换,实际上是一种可以用机械化方式完成的转换。”
#3 - 编译器擅长编写状态机:
“如果你引入允许你指示何时想要让步的语法,你就可以让编译器编写状态机。
这就是await的作用。Await基本上是说,我想在这里让步,我想让步这个promise,然后当promise完成时,我希望你回到这里继续执行。
然后编译器围绕它编写一个状态机,实际上将其转化为一个大的switch语句,并将所有在await期间存活的状态移到堆分配的内存中。这样它就可以被带回。
完成所有这些工作正是编译器所擅长的。所以这就是我们的想法:我们有这种新的编程风格,使用promise或等效于promise的东西,以及让步的能力,然后我们有回调。但是尝试以那种风格编写程序,也正是JavaScript深受其害的地方——比如所有这些回调风格的东西。
使用Async和Await,你得到一个错觉,你只是在编写普通的顺序代码,然后编译器为你完成了痛苦的转换。
事实证明这非常有用。”
#1 - async/await旨在解决事件循环模型中的一个常见问题:
“很多语言围绕协作式多任务构建,即它们有一个事件循环来调度事件。然后你处理事件,再返回到事件处理循环。这一切都在单线程中协作运行。
这样做的问题是,如果你要进行一些长时间运行的工作:如何在这段长时间运行的工作中间停止并协作地返回到事件循环?然后当我的结果准备好时,我可以回来继续执行。”
#2 - 状态机是解决方案,但难以构建:
“要在那种反转架构中做到这一点,你必须构建一个状态机。
状态机对人类来说出了名地难以实现,因为你必须将所有状态从堆栈移到对象中。然后你有一个大的case语句包裹你的整个逻辑。要理清思路简直是个噩梦。
但是,从串行执行代码到状态机的转换,即延续传递风格的转换,实际上是一种可以用机械化方式完成的转换。”
#3 - 编译器擅长编写状态机:
“如果你引入允许你指示何时想要让步的语法,你就可以让编译器编写状态机。
这就是await的作用。Await基本上是说,我想在这里让步,我想让步这个promise,然后当promise完成时,我希望你回到这里继续执行。
然后编译器围绕它编写一个状态机,实际上将其转化为一个大的switch语句,并将所有在await期间存活的状态移到堆分配的内存中。这样它就可以被带回。
完成所有这些工作正是编译器所擅长的。所以这就是我们的想法:我们有这种新的编程风格,使用promise或等效于promise的东西,以及让步的能力,然后我们有回调。但是尝试以那种风格编写程序,也正是JavaScript深受其害的地方——比如所有这些回调风格的东西。
使用Async和Await,你得到一个错觉,你只是在编写普通的顺序代码,然后编译器为你完成了痛苦的转换。
事实证明这非常有用。”