【问题标题】:How can I timeout a promise in Raku?如何让 Raku 中的承诺超时?
【发布时间】:2020-02-06 10:05:53
【问题描述】:

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

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

但是我怎样才能安排它被破坏呢?具体来说,我正在考虑一个“超时”的承诺,以便它有最多一定的时间来保持,否则它将失败。

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

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

但这感觉有点……浪费。有没有更好的方法来做到这一点?

【问题讨论】:

    标签: promise raku


    【解决方案1】:

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

    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 范式,其中有一个取消模型(关闭水龙头)。

    【讨论】:

    • 谢谢。这很有用。至少它让我们知道承诺很便宜(!)并且像你建议的那样使用它们,或者按照我最初的想法使用它们是可以的。仍然感觉应该有一种(更多?)直截了当的方式来表达“如果这个承诺没有在 X 秒内兑现,那么就认为它已经被打破了”。我知道这并不是在所有情况下都有意义,但我认为在某些情况下绝对有意义。
    • 它可能会在未来出现,但可能只有当我们在核心中也有某种Promise 取消条款时,因为它的语义会与这些条款有些关联。
    猜你喜欢
    • 1970-01-01
    • 2016-07-18
    • 2018-11-19
    • 2018-09-04
    • 2020-07-19
    • 1970-01-01
    • 2019-07-07
    • 1970-01-01
    • 2021-02-25
    相关资源
    最近更新 更多