
148
|
第
6
章
正如我先前所说的那样,正确的解决方案是对等待句柄做备忘,而不是结果:
async function
time_consuming_op(): Awaitable<string> {
static
$handle =
null
;
if
($handle ===
null
) {
$handle = time_consuming_op_impl();
//
不要在这里等待!
}
return await
$handle;
//
改在这里进行等待
}
这可能和直觉相违背,因为函数在每次执行甚至在命中缓存的时候都要等待。但这是个
好事情:在除第一次之外的每次执行中,
$handle
都不是
null
,所以
time_consuming_
op_impl()
的新实例并不会开始。已经存在的那个实例的结果将会被共享。
“竞态条件”已经过去了。早期列出的事件序列已经不再可能发生:
time_consuming_
op()
在发现缓存为空和填充缓存的过程中,并不会被暂停。
one()
和
two()
两个函数将
会等待同一个等待句柄:就是在
time_consuming_op()
中被缓存的那个。这并没有发生
什么错误。它们将会等待这个句柄完成。一旦完成,它们都会收到对应的结果。
6.6
异步扩展
在本节中,我们将详细学习
HHVM 3.6
中的四个异步扩展,分别是
MySQL
、
MCRouter
、
cURL
和
streams
。
语言级别的异步组件在
3.6
之前的几个版本中已被包含,但是这些扩展在
3.6
中是全新
的
注
7
。它们中的一些还不是特性完成的状态,但是它们将会在未来版本中得到改进。 ...