React块中whenever何时处理事件?Socket监听等待方案哪个正确?
React块中whenever的执行时机与Socket监听就绪等待方案分析
一、React块中的whenever何时开始处理事件?
react块在初始化阶段会立即处理所有whenever声明:它会立刻订阅对应的Supply/Channel,但whenever后面的代码块(即事件触发时执行的逻辑),要等到目标Supply/Channel产生事件时才会运行。
二、三种方案的正确性分析
1. 使用do的方案(错误)
my $p = Promise.new; start { react { $p.keep: do whenever IO::Socket::Async.listen( "127.0.0.1", 4528 ) -> $c { ... } } }; await $p;
do在这里仅作为语法糖让表达式合法,并没有改变whenever的触发逻辑。IO::Socket::Async.listen返回的Supply只有在有客户端连接接入时才会产生事件,因此$p.keep永远不会被调用(除非有客户端连入),无法实现“等待端口就绪”的需求。
2. 遵循代码顺序的方案(正确)
my $p = Promise.new; start { react { whenever IO::Socket::Async.listen( "127.0.0.1", 4528 ) -> $c { ... } $p.keep; } }; await $p;
react块的执行是线性的:
- 首先执行
whenever语句,完成对listen返回Supply的订阅; - 而
IO::Socket::Async.listen是同步完成端口绑定与监听的——只要它返回,就意味着端口已经处于监听状态; - 之后执行
$p.keep,此时await $p就能正确等待到Socket就绪的时刻。
这个方案完全符合需求,能保证后续线程等待到端口真正监听的状态。
3. 使用阶段器INIT的方案(错误)
my $p = Promise.new; start { react { whenever IO::Socket::Async.listen( "127.0.0.1", 4528 ) -> $c { INIT $p.keep; # ERROR, variable undefined } } }; await $p;
Perl的阶段器INIT是在编译阶段之后、运行阶段之前执行的,此时my $p = Promise.new还未被运行时执行,$p变量根本没有初始化,因此会报“变量未定义”的错误。此外,INIT的执行时机和react块、Socket监听的逻辑完全无关,根本无法用来检测Socket是否就绪。
内容的提问来源于stack exchange,提问作者Pawel Pabian bbkr
相关产品推荐
相关产品推荐

