PHP Classes

File: vendor/react/promise-timer/src/functions.php

Recommend this page to a friend!
  Classes of Adeleye Ayodeji   Simple PHP Chat with Websocket   vendor/react/promise-timer/src/functions.php   Download  
File: vendor/react/promise-timer/src/functions.php
Role: Example script
Content type: text/plain
Description: Example script
Class: Simple PHP Chat with Websocket
Implements a chat system using Websockets
Author: By
Last change:
Date: 15 days ago
Size: 12,678 bytes
 

Contents

Class file image Download
<?php namespace React\Promise\Timer; use React\EventLoop\Loop; use React\EventLoop\LoopInterface; use React\Promise\CancellablePromiseInterface; use React\Promise\Promise; use React\Promise\PromiseInterface; /** * Cancel operations that take *too long*. * * You need to pass in an input `$promise` that represents a pending operation * and timeout parameters. It returns a new promise with the following * resolution behavior: * * - If the input `$promise` resolves before `$time` seconds, resolve the * resulting promise with its fulfillment value. * * - If the input `$promise` rejects before `$time` seconds, reject the * resulting promise with its rejection value. * * - If the input `$promise` does not settle before `$time` seconds, *cancel* * the operation and reject the resulting promise with a [`TimeoutException`](#timeoutexception). * * Internally, the given `$time` value will be used to start a timer that will * *cancel* the pending operation once it triggers. This implies that if you * pass a really small (or negative) value, it will still start a timer and will * thus trigger at the earliest possible time in the future. * * If the input `$promise` is already settled, then the resulting promise will * resolve or reject immediately without starting a timer at all. * * This function takes an optional `LoopInterface|null $loop` parameter that can be used to * pass the event loop instance to use. You can use a `null` value here in order to * use the [default loop](https://github.com/reactphp/event-loop#loop). This value * SHOULD NOT be given unless you're sure you want to explicitly use a given event * loop instance. * * A common use case for handling only resolved values looks like this: * * ```php * $promise = accessSomeRemoteResource(); * React\Promise\Timer\timeout($promise, 10.0)->then(function ($value) { * // the operation finished within 10.0 seconds * }); * ``` * * A more complete example could look like this: * * ```php * $promise = accessSomeRemoteResource(); * React\Promise\Timer\timeout($promise, 10.0)->then( * function ($value) { * // the operation finished within 10.0 seconds * }, * function ($error) { * if ($error instanceof React\Promise\Timer\TimeoutException) { * // the operation has failed due to a timeout * } else { * // the input operation has failed due to some other error * } * } * ); * ``` * * Or if you're using [react/promise v2.2.0](https://github.com/reactphp/promise) or up: * * ```php * React\Promise\Timer\timeout($promise, 10.0) * ->then(function ($value) { * // the operation finished within 10.0 seconds * }) * ->otherwise(function (React\Promise\Timer\TimeoutException $error) { * // the operation has failed due to a timeout * }) * ->otherwise(function ($error) { * // the input operation has failed due to some other error * }) * ; * ``` * * As discussed above, the [`timeout()`](#timeout) function will take care of * the underlying operation if it takes *too long*. In this case, you can be * sure the resulting promise will always be rejected with a * [`TimeoutException`](#timeoutexception). On top of this, the function will * try to *cancel* the underlying operation. Responsibility for this * cancellation logic is left up to the underlying operation. * * - A common use case involves cleaning up any resources like open network * sockets or file handles or terminating external processes or timers. * * - If the given input `$promise` does not support cancellation, then this is a * NO-OP. This means that while the resulting promise will still be rejected, * the underlying input `$promise` may still be pending and can hence continue * consuming resources * * On top of this, the returned promise is implemented in such a way that it can * be cancelled when it is still pending. Cancelling a pending promise will * cancel the underlying operation. As discussed above, responsibility for this * cancellation logic is left up to the underlying operation. * * ```php * $promise = accessSomeRemoteResource(); * $timeout = React\Promise\Timer\timeout($promise, 10.0); * * $timeout->cancel(); * ``` * * For more details on the promise cancellation, please refer to the * [Promise documentation](https://github.com/reactphp/promise#cancellablepromiseinterface). * * If you want to wait for multiple promises to resolve, you can use the normal * promise primitives like this: * * ```php * $promises = array( * accessSomeRemoteResource(), * accessSomeRemoteResource(), * accessSomeRemoteResource() * ); * * $promise = React\Promise\all($promises); * * React\Promise\Timer\timeout($promise, 10)->then(function ($values) { * // *all* promises resolved * }); * ``` * * The applies to all promise collection primitives alike, i.e. `all()`, * `race()`, `any()`, `some()` etc. * * For more details on the promise primitives, please refer to the * [Promise documentation](https://github.com/reactphp/promise#functions). * * @param PromiseInterface<mixed, \Exception|mixed> $promise * @param float $time * @param ?LoopInterface $loop * @return PromiseInterface<mixed, TimeoutException|\Exception|mixed> */ function timeout(PromiseInterface $promise, $time, LoopInterface $loop = null) { // cancelling this promise will only try to cancel the input promise, // thus leaving responsibility to the input promise. $canceller = null; if ($promise instanceof CancellablePromiseInterface || (!\interface_exists('React\Promise\CancellablePromiseInterface') && \method_exists($promise, 'cancel'))) { // pass promise by reference to clean reference after cancellation handler // has been invoked once in order to avoid garbage references in call stack. $canceller = function () use (&$promise) { $promise->cancel(); $promise = null; }; } if ($loop === null) { $loop = Loop::get(); } return new Promise(function ($resolve, $reject) use ($loop, $time, $promise) { $timer = null; $promise = $promise->then(function ($v) use (&$timer, $loop, $resolve) { if ($timer) { $loop->cancelTimer($timer); } $timer = false; $resolve($v); }, function ($v) use (&$timer, $loop, $reject) { if ($timer) { $loop->cancelTimer($timer); } $timer = false; $reject($v); }); // promise already resolved => no need to start timer if ($timer === false) { return; } // start timeout timer which will cancel the input promise $timer = $loop->addTimer($time, function () use ($time, &$promise, $reject) { $reject(new TimeoutException($time, 'Timed out after ' . $time . ' seconds')); // try to invoke cancellation handler of input promise and then clean // reference in order to avoid garbage references in call stack. if ($promise instanceof CancellablePromiseInterface || (!\interface_exists('React\Promise\CancellablePromiseInterface') && \method_exists($promise, 'cancel'))) { $promise->cancel(); } $promise = null; }); }, $canceller); } /** * Create a new promise that resolves in `$time` seconds. * * ```php * React\Promise\Timer\sleep(1.5)->then(function () { * echo 'Thanks for waiting!' . PHP_EOL; * }); * ``` * * Internally, the given `$time` value will be used to start a timer that will * resolve the promise once it triggers. This implies that if you pass a really * small (or negative) value, it will still start a timer and will thus trigger * at the earliest possible time in the future. * * This function takes an optional `LoopInterface|null $loop` parameter that can be used to * pass the event loop instance to use. You can use a `null` value here in order to * use the [default loop](https://github.com/reactphp/event-loop#loop). This value * SHOULD NOT be given unless you're sure you want to explicitly use a given event * loop instance. * * The returned promise is implemented in such a way that it can be cancelled * when it is still pending. Cancelling a pending promise will reject its value * with a `RuntimeException` and clean up any pending timers. * * ```php * $timer = React\Promise\Timer\sleep(2.0); * * $timer->cancel(); * ``` * * @param float $time * @param ?LoopInterface $loop * @return PromiseInterface<void, \RuntimeException> */ function sleep($time, LoopInterface $loop = null) { if ($loop === null) { $loop = Loop::get(); } $timer = null; return new Promise(function ($resolve) use ($loop, $time, &$timer) { // resolve the promise when the timer fires in $time seconds $timer = $loop->addTimer($time, function () use ($resolve) { $resolve(); }); }, function () use (&$timer, $loop) { // cancelling this promise will cancel the timer, clean the reference // in order to avoid garbage references in call stack and then reject. $loop->cancelTimer($timer); $timer = null; throw new \RuntimeException('Timer cancelled'); }); } /** * [Deprecated] Create a new promise that resolves in `$time` seconds with the `$time` as the fulfillment value. * * ```php * React\Promise\Timer\resolve(1.5)->then(function ($time) { * echo 'Thanks for waiting ' . $time . ' seconds' . PHP_EOL; * }); * ``` * * Internally, the given `$time` value will be used to start a timer that will * resolve the promise once it triggers. This implies that if you pass a really * small (or negative) value, it will still start a timer and will thus trigger * at the earliest possible time in the future. * * This function takes an optional `LoopInterface|null $loop` parameter that can be used to * pass the event loop instance to use. You can use a `null` value here in order to * use the [default loop](https://github.com/reactphp/event-loop#loop). This value * SHOULD NOT be given unless you're sure you want to explicitly use a given event * loop instance. * * The returned promise is implemented in such a way that it can be cancelled * when it is still pending. Cancelling a pending promise will reject its value * with a `RuntimeException` and clean up any pending timers. * * ```php * $timer = React\Promise\Timer\resolve(2.0); * * $timer->cancel(); * ``` * * @param float $time * @param ?LoopInterface $loop * @return PromiseInterface<float, \RuntimeException> * @deprecated 1.8.0 See `sleep()` instead * @see sleep() */ function resolve($time, LoopInterface $loop = null) { return sleep($time, $loop)->then(function() use ($time) { return $time; }); } /** * [Deprecated] Create a new promise which rejects in `$time` seconds with a `TimeoutException`. * * ```php * React\Promise\Timer\reject(2.0)->then(null, function (React\Promise\Timer\TimeoutException $e) { * echo 'Rejected after ' . $e->getTimeout() . ' seconds ' . PHP_EOL; * }); * ``` * * Internally, the given `$time` value will be used to start a timer that will * reject the promise once it triggers. This implies that if you pass a really * small (or negative) value, it will still start a timer and will thus trigger * at the earliest possible time in the future. * * This function takes an optional `LoopInterface|null $loop` parameter that can be used to * pass the event loop instance to use. You can use a `null` value here in order to * use the [default loop](https://github.com/reactphp/event-loop#loop). This value * SHOULD NOT be given unless you're sure you want to explicitly use a given event * loop instance. * * The returned promise is implemented in such a way that it can be cancelled * when it is still pending. Cancelling a pending promise will reject its value * with a `RuntimeException` and clean up any pending timers. * * ```php * $timer = React\Promise\Timer\reject(2.0); * * $timer->cancel(); * ``` * * @param float $time * @param LoopInterface $loop * @return PromiseInterface<void, TimeoutException|\RuntimeException> * @deprecated 1.8.0 See `sleep()` instead * @see sleep() */ function reject($time, LoopInterface $loop = null) { return sleep($time, $loop)->then(function () use ($time) { throw new TimeoutException($time, 'Timer expired after ' . $time . ' seconds'); }); }