Как я могу прервать обещание в Раку?

9

Я знаю, что могу запланировать, Promiseчтобы быть сохраненным в течение определенного количества времени с

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

но как я могу запланировать его нарушение? В частности, я имею в виду обещание, которое «истечет», так что у него будет определенное количество времени для выполнения, иначе оно не будет выполнено.

Я могу сделать это с другим Promise, вот так:

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

Но это кажется немного ... расточительным. Есть лучший способ сделать это?

JJA
источник

Ответы:

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, передаст результат или исключение и в противном случае выдаст исключение по тайм-ауту.

Следует помнить, что они фактически не влияют на отмену незавершенного производства. Это может не иметь значения, или это может быть важно. Если последнее, вы, вероятно, захотите либо:

  • A, Promiseкоторый вы используете для передачи отмены, произошедшей; вы сохраняете его при отмене и опрашиваете его в коде, который будет выполнять отмену
  • Чтобы посмотреть, используя Supplyвместо этого парадигму, где есть модель отмены (закрытие крана).
Джонатан Уортингтон
источник
3
Спасибо. Это полезно И, по крайней мере, все сводится к тому, что обещания дешевы (!), И их использование, как вы предлагаете, или то, о чем я изначально думал, это нормально. Мне все еще кажется, что должен быть (более?) Прямой способ сказать: «Если это обещание не было выполнено в течение X секунд, то считайте его нарушенным». Я понимаю, что это не будет иметь смысла во всех случаях, но я думаю, что это определенно имеет смысл в некоторых случаях.
JJA
3
Вероятно, это произойдет в будущем, однако, вероятно, только тогда, когда у нас Promiseв ядре также будут какие-то положения об отмене, поскольку его семантика будет несколько связана с ними.
Джонатан Уортингтон