我该如何在Raku中设置Promise的超时时间?

9
我知道我可以使用 Promise 来在指定时间后保持其执行。
my $promise = Promise.in($seconds);

但是我该如何安排它被中断?具体来说,我想一个承诺将会"超时",这样就有一定的时间来实现它,否则将失败。
我可以用另一个Promise来实现这个:
my $promise = Promise.new;
...
Promise.in($seconds).then: { $promise.break };

但这种方式有些浪费。有没有更好的方法呢?

1个回答

10

一种常见的模式是编写类似于以下内容:

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

尽管这并不表现为一个破碎的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)
    }
}

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

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

  • 使用 Promise 来传达取消已经发生;在取消时保留它,并在将执行取消的代码中轮询它
  • 考虑改用 Supply 范例,其中有一个取消模型(关闭水龙头)。

3
谢谢。这很有用。至少它让人们明白承诺是廉价的,可以像你建议的那样使用它们,或者像我最初想的那样使用它们也可以。但仍然感觉应该有一种更加直接的方式来表达“如果这个承诺在X秒内没有兑现,就认为它已经破裂了”。我知道这在所有情况下都不合适,但我认为它在某些情况下绝对是有意义的。 - jja
3
很可能会在未来出现,但只有在核心中有某种Promise取消机制时才会出现,因为其语义与这些机制有些关联。 - Jonathan Worthington

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接