如何在 Raku 中超时承诺?

jja*_*jja 9 promise raku

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

my $promise = Promise.in($seconds);
Run Code Online (Sandbox Code Playgroud)

但我怎样才能安排它被打破?具体来说,我正在考虑一个会“超时”的承诺,这样它就有一定的时间来保留,否则就会失败。

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

my $promise = Promise.new;
...
Promise.in($seconds).then: { $promise.break };
Run Code Online (Sandbox Code Playgroud)

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

Jon*_*ton 10

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

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

这并没有表现为一个错误的Promise,尽管这并不完全是坏事(因为无论如何在许多情况下您都需要区分取消与错误,因此您仍然必须对异常类型进行一些匹配)。这种保理还有一个优势,$the-promise即您不必保持/中断。

人们也可以用这样的方式来包装它:

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

这将再次与 any 一起使用$promise,传递结果或异常,否则抛出超时异常。

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

  • 一种 Promise,你用它来传达消除已经发生; 您在取消时保留它,并在将执行取消的代码中对其进行轮询
  • 看看使用Supply范式,那里有一个取消模型(关闭水龙头)。

  • 谢谢。这很有用。至少它让我们明白,承诺是廉价的(!)并且按照你的建议或我最初的想法使用它们是可以的。仍然感觉应该有一种(更?)直接的方式来表达“如果这个承诺没有在 X 秒内兑现,那么就认为它被打破了”。我知道这并不是在所有情况下都有意义,但我认为在某些情况下它绝对有意义。 (3认同)
  • 它可能会在未来出现,但可能只有当我们在核心中也有某种“Promise”取消条款时,因为它的语义将与这些条款有所联系。 (3认同)