楽で約束をタイムアウトするにはどうすればよいですか?


9

私はをPromise一定の時間内に維持するようにスケジュールできることを知っています

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

しかし、どうすれば壊れるようにスケジュールできますか?具体的には、「タイムアウト」して、一定の時間が経過すると失敗するという約束を考えています。

私は次のPromiseように別のでこれを行うことができます:

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

しかし、これは少し...無駄に感じます。これを行うより良い方法はありますか?

回答:


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)
    }
}

これは再びany $promiseで機能し、結果または例外を渡し、そうでない場合はタイムアウトした例外をスローします。

これらすべてに留意することは、進行中の作業のキャンセルには実際には影響しないということです。それは問題ではないかもしれません、またはそれは重要かもしれません。後者の場合は、おそらく次のいずれかが必要になります。

  • Promiseキャンセルが行われたことを伝えるために使用するA。キャンセルするときにそれを保持し、キャンセルを行うコードでポーリングします
  • Supply代わりに、(タップを閉じる)キャンセルモデルがあるパラダイムの使用方法を確認します。

3
ありがとう。これは便利です。そして、少なくとも、それは約束が安い(!)それでも、「この約束がX秒以内に維持されなかった場合は、それが破られたと見なしてください」という(もっと?)簡単な方法があるはずです。私はそれがすべてのケースで意味をなさないことを理解しますが、それはいくつかのケースでは間違いなく理にかなっていると思います。
jja

3
それはおそらく将来的に来るでしょう、しかし、おそらくPromiseその意味論がそれらといくらか結び付けられるので、コアに何らかの種類のキャンセル規定があるときだけでしょう。
ジョナサンワージントン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.