我如何使 Raku 中的承诺超时?

How can I timeout a promise in Raku?

我知道我可以安排 Promise 在给定的时间内保存

my $promise = Promise.in($seconds);

但是我怎样才能安排它坏掉呢?具体来说,我正在考虑一个 "timeout" 的承诺,这样它就可以保留一定的时间,否则就会失败。

我可以用另一个 Promise 来做这个,就像这样:

my $promise = Promise.new;
...
Promise.in($seconds).then: { $promise.break };

但这感觉有点……浪费。有更好的方法吗?

一个常见的模式是这样写:

await Promise.anyof($the-promise, Promise.in(10));
if $the-promise {
    # it finished ahead of the timeout
}
else {
    # it timed out
}

这并没有表现为损坏的 Promise,尽管这并非全是坏事(因为无论如何在许多情况下您都需要区分取消与错误,因此您仍然需要进行一些匹配关于异常类型)。此因式分解还有一个优点,即 $the-promise 不必是您有权访问 keep/break.

的一个因式分解

也可以这样总结:

class TimedOut is Exception {}
sub timeout($promise, $time) {
    start {
        await Promise.anyof($promise, Promise.in($time));
        $promise ?? await($promise) !! die(TimedOut.new)
    }
}

这将再次与任何 $promise 一起工作,传递结果或异常,否则抛出超时异常。

所有这些要记住的是,它们实际上不会影响任何正在进行的工作的取消。这可能无关紧要,也可能很重要。如果是后者,您可能需要:

  • A Promise 用于传达已取消;你在取消时保留它,并在执行取消的代码中轮询它
  • 查看使用 Supply 范例,其中有一个取消模型(关闭水龙头)。