我编写了这个测试程序:
await Promise.anyof(
Promise.allof((^5).map: {start { sleep 10; say "done $_" } }),
Promise.in(5).then: { say 'ouch' }
);
sleep 10;
当第二个Promise超时时,它会打印'ouch'并等待退出,但是第一个Promise的代码块仍在运行。再过五秒钟后,其五个过程结束并打印“完成”:
$ ./test1.p6
ouch
done 0
done 1
done 2
done 3
done 4
我试图终止将其分配给变量的第一个诺言,然后从第二个诺言中调用.break
方法,但这是行不通的。
有没有办法取消第一个承诺以及其他五个次要承诺?
答案 0 :(得分:5)
您必须以某种方式告诉该过程它不必完成。
my $cancel = Cancellation.new;
await Promise.anyof(
Promise.allof(
(^5).map: {
last if $cancel.cancelled;
start {
sleep 10;
say "done $_" unless $cancel.cancelled
}
}
),
Promise.in(5).then: {
$cancel.cancel;
say 'ouch'
}
);
如果您希望取消Promise.in()
之类的内容,请从looking at the existing code开始。
method in(Promise:U: $seconds, :$scheduler = $*SCHEDULER) {
my $p := self.new(:$scheduler);
my $vow := $p.vow;
$scheduler.cue({ $vow.keep(True) }, :in($seconds));
$p
}
请注意,$scheduler.cue
的结果是取消。
为了简单起见,我将在一个类中包装Promise和Cancellation。
(我不想重新实现所有方法)。
class Cancellable-Timer {
has Promise $.Promise;
has $!vow;
has Cancellation $!cancel;
method !SET-SELF ( $!promise, $!vow, $!cancel ){
self
}
method in (::?CLASS:U: $seconds, :$scheduler = $*SCHEDULER) {
my $p := Promise.new(:$scheduler);
my $vow := $p.vow;
my $cancel = $scheduler.cue({ $vow.keep(True) }, :in($seconds));
self.bless!SET-SELF($p,$vow,$cancel);
}
method cancel ( --> Nil ) {
# potential concurrency problem
if $!Promise.status == Planned {
$!cancel.cancel; # cancel the timer
$!vow.break("cancelled"); # break the Promise
}
}
method cancelled () {
# Ignore any concurrency problems by using the Promise
# as the sole source of truth.
$!Promise.status ~~ PromiseStatus::Broken
}
}
my $timer = Cancellable-Timer.in(1);
my $say = $timer.Promise.then: *.say;
Promise.in(0.1).then: {$timer.cancel};
await $say;
请注意,以上课程只是初稿。
答案 1 :(得分:3)
尝试 何时 :
$ perl6 -e '
react {
for ^5 -> $num {
whenever start { sleep 10 } {
say "done $num"
}
}
whenever Promise.in: 5 {
say "ouch";
done
}
}
' ouch