我正在尝试使用计时器类编写观察者模式,该计时器类以给定间隔调用其订阅者。一直试图理解Perl6中的promises概念。
class Timer does Observable
{
has Promise $!p;
has Int $!interval;
has Bool $!active = False;
submethod BUILD(Int :$!interval) {}
method start {
$!p = Promise.start( {
$!active = True;
loop {
sleep($!interval);
@!action_listeners>>.actionPerformed(ActionEvent.new);
if !$!active {$!p.keep}
}
});
}
method stop {
$!active = False;
}
}
观察者角色只是拥有一个带有订阅者的数组。当然,我应该有一种方法来更新角色中的所有订户。
role Observable {
has ActionListener @!action_listeners;
method addActionListener(ActionListener $al){
@!action_listeners.push($al);
}
method removeActionListener{
@!action_listeners.pop;
}
}
ActionListener角色仅具有一个actionPerformed方法。 ActionEvent类可能不是必需的,目前只是一个空类。
role ActionListener
{
method actionPerformed(ActionEvent $e) { ... }
}
从脚本运行:
my Subscriber $s = Subscriber.new;
my Timer $t = Timer.new(interval => 1);
$t.start;
$t.addActionListener($s);
$t.addActionListener(Subscriber.new);
.... #doing stuff that lasts for a while
$t.stop;
订户类实现ActionListener角色(具有一个称为actionPerformed的方法)。
尽管可以正常工作:在我调用计时器的stop方法之前,将调用订户的actionPerformed方法。虽然没有适当的方法来删除给定的订户。我还想知道是否存在一种更好的方式来保持/违反承诺,即从外部给定代码循环。
我基本上想知道我是否会错过Perl6的内置功能?我在重新发明轮子吗?
答案 0 :(得分:8)
要进一步回答重新发明轮子的问题:您应该看看Supply。 Supply
是Observable
的Perl 6术语,而Tap
是Subscription
的Perl 6术语。
为了获得可观察到的以固定间隔调用订户的方法,可以使用the interval class method of the Supply type。您将在.tap
调用的结果上调用.interval
来注册一个代码块,只要Supply
emit
是一个值和{{1}的结果时就运行}调用是.tap
对象,您可以用来关闭订阅。
答案 1 :(得分:6)
回答您的问题“我是在重新发明轮子吗?”。可能。
您实际上可以要求当前的ThreadPoolScheduler
(又名$*SCHEDULER
)提示一段要间隔运行的代码:
my $canceller = $*SCHEDULER.cue( { say $++ }, every => 0.2 );
sleep 2;
# 0 1 2 3 4 5 6 7 8 9
$canceller.cancel;
say "stopped"; # no numbers should be seen afterward
# stopped
sleep 1; # keep from exiting immediately
这不涉及任何Promise
,因此,如果您的目标是更多地了解Promise
,那么不是。如果要创建观察者模式,这可能是创建它的最简洁的方法。