既然async/await具有很强的传染性,那么是否可以从编程语言层面将其变成一个默认行为?

基于我对一些加入了async/await特性的语言的使用体验,我发现只要有一处使用了async,那么它的整个调用链上的函数都最好改成异步的;同时,很多…
关注者
357
被浏览
205,123
登录后你可以
不限量看优质回答私信答主深度交流精彩内容一键收藏

await的作用是把一个Promise<T>(或者Task)变成T,所以应该是await而不是defer,因为await做了额外的工作,defer没有,为什么要为“什么都不做”创造关键字,而将默认行为设置成“做额外的事”呢?

那么为什么要有async呢,因为如果一个函数明明return的是T但是它的返回值却是Promise,这样看起来会很怪,但是如果你看到这个函数是async的,那么你就不会觉得奇怪,因为所有async函数的返回值都是Promise,无论它在函数体内return的是什么。

另外,如果非async函数可以是异步的,但是某次调用路径上没有await,那么该函数将返回T而不是Promise,因为他不是async函数。那么,按照题主的语法,任何一个宣称返回T的函数,其真实返回值类型都可能会是T | Promise<T>,而调用者对于将接收到哪个值是一无所知的。JS表示这种我们见得多了,但是py和cs能受得了这个吗?


所以不采用“自动async”的实现,除了“兼容性”,也是为了语义上的明确性,让读代码的人和使用者都少一些心智负担吧。

不过反过来,“自动async消除”我倒是觉得可以有(限js,因为它会让Promise<T>变成T | Promise<T>),因为我们await一个非Promise的时候会得到它本身,那么引擎(或者编译器/bundler)在探测到某个async函数没有使用await,或者没有await一个需要await的Promise,并且(所有)调用者(都)使用了await而不期待一个Promise(并且该函数没有被export或者bundler被配置为无视export),这时是可以让它直接返回T而精确得不改变语义的。

进一步的我们可以采用sync关键字而不是async关键字,函数默认是可自动消除的async的,如果一个函数是sync的,那么它不能是异步的。

但是这种实现就真的有兼容性问题了。