@@ -8,16 +8,10 @@ A trivial implementation of timeouts for `Promise`s, built on top of [ReactPHP](
88
99* [ Usage] ( #usage )
1010 * [ timeout()] ( #timeout )
11- * [ Timeout cancellation] ( #timeout-cancellation )
12- * [ Cancellation handler] ( #cancellation-handler )
13- * [ Input cancellation] ( #input-cancellation )
14- * [ Output cancellation] ( #output-cancellation )
15- * [ Collections] ( #collections )
1611 * [ resolve()] ( #resolve )
17- * [ Resolve cancellation] ( #resolve-cancellation )
1812 * [ reject()] ( #reject )
19- * [ Reject cancellation] ( #reject-cancellation )
2013 * [ TimeoutException] ( #timeoutexception )
14+ * [ getTimeout()] ( #gettimeout )
2115* [ Install] ( #install )
2216* [ Tests] ( #tests )
2317* [ License] ( #license )
@@ -51,19 +45,26 @@ Timer\timeout(…);
5145
5246### timeout()
5347
54- The ` timeout(PromiseInterface $promise, $time, LoopInterface $loop = null) ` function
55- can be used to * cancel* operations that take * too long* .
56- You need to pass in an input ` $promise ` that represents a pending operation and timeout parameters.
57- It returns a new ` Promise ` with the following resolution behavior:
48+ The ` timeout(PromiseInterface<mixed, Exception|mixed> $promise, float $time, ?LoopInterface $loop = null): PromiseInterface<mixed, TimeoutException|Exception|mixed> ` function can be used to
49+ cancel operations that take * too long* .
5850
59- * If the input ` $promise ` resolves before ` $time ` seconds, resolve the resulting promise with its fulfillment value.
60- * If the input ` $promise ` rejects before ` $time ` seconds, reject the resulting promise with its rejection value.
61- * If the input ` $promise ` does not settle before ` $time ` seconds, * cancel* the operation and reject the resulting promise with a [ ` TimeoutException ` ] ( #timeoutexception ) .
51+ You need to pass in an input ` $promise ` that represents a pending operation
52+ and timeout parameters. It returns a new promise with the following
53+ resolution behavior:
54+
55+ - If the input ` $promise ` resolves before ` $time ` seconds, resolve the
56+ resulting promise with its fulfillment value.
57+
58+ - If the input ` $promise ` rejects before ` $time ` seconds, reject the
59+ resulting promise with its rejection value.
60+
61+ - If the input ` $promise ` does not settle before ` $time ` seconds, * cancel*
62+ the operation and reject the resulting promise with a [ ` TimeoutException ` ] ( #timeoutexception ) .
6263
6364Internally, the given ` $time ` value will be used to start a timer that will
64- * cancel* the pending operation once it triggers.
65- This implies that if you pass a really small (or negative) value, it will still
66- start a timer and will thus trigger at the earliest possible time in the future.
65+ * cancel* the pending operation once it triggers. This implies that if you
66+ pass a really small (or negative) value, it will still start a timer and will
67+ thus trigger at the earliest possible time in the future.
6768
6869If the input ` $promise ` is already settled, then the resulting promise will
6970resolve or reject immediately without starting a timer at all.
@@ -117,95 +118,25 @@ React\Promise\Timer\timeout($promise, 10.0)
117118;
118119```
119120
120- #### Timeout cancellation
121-
122- As discussed above, the [ ` timeout() ` ] ( #timeout ) function will * cancel* the
123- underlying operation if it takes * too long* .
124- This means that you can be sure the resulting promise will then be rejected
125- with a [ ` TimeoutException ` ] ( #timeoutexception ) .
126-
127- However, what happens to the underlying input ` $promise ` is a bit more tricky:
128- Once the timer fires, we will try to call
129- [ ` $promise->cancel() ` ] ( https://github.com/reactphp/promise#cancellablepromiseinterfacecancel )
130- on the input ` $promise ` which in turn invokes its [ cancellation handler] ( #cancellation-handler ) .
131-
132- This means that it's actually up the input ` $promise ` to handle
133- [ cancellation support] ( https://github.com/reactphp/promise#cancellablepromiseinterface ) .
134-
135- * A common use case involves cleaning up any resources like open network sockets or
136- file handles or terminating external processes or timers.
137-
138- * If the given input ` $promise ` does not support cancellation, then this is a NO-OP.
139- This means that while the resulting promise will still be rejected, the underlying
140- input ` $promise ` may still be pending and can hence continue consuming resources.
141-
142- See the following chapter for more details on the cancellation handler.
143-
144- #### Cancellation handler
145-
146- For example, an implementation for the above operation could look like this:
147-
148- ``` php
149- function accessSomeRemoteResource()
150- {
151- return new Promise(
152- function ($resolve, $reject) use (& $socket) {
153- // this will be called once the promise is created
154- // a common use case involves opening any resources and eventually resolving
155- $socket = createSocket();
156- $socket->on('data', function ($data) use ($resolve) {
157- $resolve($data);
158- });
159- },
160- function ($resolve, $reject) use (& $socket) {
161- // this will be called once calling `cancel()` on this promise
162- // a common use case involves cleaning any resources and then rejecting
163- $socket->close();
164- $reject(new \RuntimeException('Operation cancelled'));
165- }
166- );
167- }
168- ```
169-
170- In this example, calling ` $promise->cancel() ` will invoke the registered cancellation
171- handler which then closes the network socket and rejects the ` Promise ` instance.
121+ As discussed above, the [ ` timeout() ` ] ( #timeout ) function will take care of
122+ the underlying operation if it takes * too long* . In this case, you can be
123+ sure the resulting promise will always be rejected with a
124+ [ ` TimeoutException ` ] ( #timeoutexception ) . On top of this, the function will
125+ try to * cancel* the underlying operation. Responsibility for this
126+ cancellation logic is left up to the underlying operation.
172127
173- If no cancellation handler is passed to the ` Promise ` constructor, then invoking
174- its ` cancel() ` method it is effectively a NO-OP.
175- This means that it may still be pending and can hence continue consuming resources.
128+ - A common use case involves cleaning up any resources like open network
129+ sockets or file handles or terminating external processes or timers.
176130
177- For more details on the promise cancellation, please refer to the
178- [ Promise documentation ] ( https://github.com/reactphp/ promise#cancellablepromiseinterface ) .
179-
180- #### Input cancellation
131+ - If the given input ` $ promise` does not support cancellation, then this is a
132+ NO-OP. This means that while the resulting promise will still be rejected,
133+ the underlying input ` $promise ` may still be pending and can hence continue
134+ consuming resources
181135
182- Irrespective of the timeout handling, you can also explicitly ` cancel() ` the
183- input ` $promise ` at any time.
184- This means that the ` timeout() ` handling does not affect cancellation of the
185- input ` $promise ` , as demonstrated in the following example:
186-
187- ``` php
188- $promise = accessSomeRemoteResource();
189- $timeout = React\Promise\Timer\timeout($promise, 10.0);
190-
191- $promise->cancel();
192- ```
193-
194- The registered [ cancellation handler] ( #cancellation-handler ) is responsible for
195- handling the ` cancel() ` call:
196-
197- * A described above, a common use involves resource cleanup and will then * reject*
198- the ` Promise ` .
199- If the input ` $promise ` is being rejected, then the timeout will be aborted
200- and the resulting promise will also be rejected.
201- * If the input ` $promise ` is still pending, then the timout will continue
202- running until the timer expires.
203- The same happens if the input ` $promise ` does not register a
204- [ cancellation handler] ( #cancellation-handler ) .
205-
206- #### Output cancellation
207-
208- Similarily, you can also explicitly ` cancel() ` the resulting promise like this:
136+ On top of this, the returned promise is implemented in such a way that it can
137+ be cancelled when it is still pending. Cancelling a pending promise will
138+ cancel the underlying operation. As discussed above, responsibility for this
139+ cancellation logic is left up to the underlying operation.
209140
210141``` php
211142$promise = accessSomeRemoteResource();
@@ -214,54 +145,11 @@ $timeout = React\Promise\Timer\timeout($promise, 10.0);
214145$timeout->cancel();
215146```
216147
217- Note how this looks very similar to the above [ input cancellation] ( #input-cancellation )
218- example. Accordingly, it also behaves very similar.
219-
220- Calling ` cancel() ` on the resulting promise will merely try
221- to ` cancel() ` the input ` $promise ` .
222- This means that we do not take over responsibility of the outcome and it's
223- entirely up to the input ` $promise ` to handle cancellation support.
224-
225- The registered [ cancellation handler] ( #cancellation-handler ) is responsible for
226- handling the ` cancel() ` call:
227-
228- * As described above, a common use involves resource cleanup and will then * reject*
229- the ` Promise ` .
230- If the input ` $promise ` is being rejected, then the timeout will be aborted
231- and the resulting promise will also be rejected.
232- * If the input ` $promise ` is still pending, then the timout will continue
233- running until the timer expires.
234- The same happens if the input ` $promise ` does not register a
235- [ cancellation handler] ( #cancellation-handler ) .
236-
237- To re-iterate, note that calling ` cancel() ` on the resulting promise will merely
238- try to cancel the input ` $promise ` only.
239- It is then up to the cancellation handler of the input promise to settle the promise.
240- If the input promise is still pending when the timeout occurs, then the normal
241- [ timeout cancellation] ( #timeout-cancellation ) handling will trigger, effectively rejecting
242- the output promise with a [ ` TimeoutException ` ] ( #timeoutexception ) .
243-
244- This is done for consistency with the [ timeout cancellation] ( #timeout-cancellation )
245- handling and also because it is assumed this is often used like this:
246-
247- ``` php
248- $timeout = React\Promise\Timer\timeout(accessSomeRemoteResource(), 10.0);
249-
250- $timeout->cancel();
251- ```
252-
253- As described above, this example works as expected and cleans up any resources
254- allocated for the input ` $promise ` .
255-
256- Note that if the given input ` $promise ` does not support cancellation, then this
257- is a NO-OP.
258- This means that while the resulting promise will still be rejected after the
259- timeout, the underlying input ` $promise ` may still be pending and can hence
260- continue consuming resources.
261-
262- #### Collections
148+ For more details on the promise cancellation, please refer to the
149+ [ Promise documentation] ( https://github.com/reactphp/promise#cancellablepromiseinterface ) .
263150
264- If you want to wait for multiple promises to resolve, you can use the normal promise primitives like this:
151+ If you want to wait for multiple promises to resolve, you can use the normal
152+ promise primitives like this:
265153
266154``` php
267155$promises = array(
@@ -270,22 +158,23 @@ $promises = array(
270158 accessSomeRemoteResource()
271159);
272160
273- $promise = \ React\Promise\all($promises);
161+ $promise = React\Promise\all($promises);
274162
275163React\Promise\Timer\timeout($promise, 10)->then(function ($values) {
276164 // *all* promises resolved
277165});
278166```
279167
280- The applies to all promise collection primitives alike, i.e. ` all() ` , ` race() ` , ` any() ` , ` some() ` etc.
168+ The applies to all promise collection primitives alike, i.e. ` all() ` ,
169+ ` race() ` , ` any() ` , ` some() ` etc.
281170
282171For more details on the promise primitives, please refer to the
283172[ Promise documentation] ( https://github.com/reactphp/promise#functions ) .
284173
285174### resolve()
286175
287- The ` resolve($time, LoopInterface $loop = null) ` function can be used to create a new Promise that
288- resolves in ` $time ` seconds with the ` $time ` as the fulfillment value.
176+ The ` resolve(float $time, ? LoopInterface $loop = null): PromiseInterface<float, RuntimeException> ` function can be used to
177+ create a new promise that resolves in ` $time ` seconds with the ` $time ` as the fulfillment value.
289178
290179``` php
291180React\Promise\Timer\resolve(1.5)->then(function ($time) {
@@ -294,32 +183,30 @@ React\Promise\Timer\resolve(1.5)->then(function ($time) {
294183```
295184
296185Internally, the given ` $time ` value will be used to start a timer that will
297- resolve the promise once it triggers.
298- This implies that if you pass a really small (or negative) value, it will still
299- start a timer and will thus trigger at the earliest possible time in the future.
186+ resolve the promise once it triggers. This implies that if you pass a really
187+ small (or negative) value, it will still start a timer and will thus trigger
188+ at the earliest possible time in the future.
300189
301190This function takes an optional ` LoopInterface|null $loop ` parameter that can be used to
302191pass the event loop instance to use. You can use a ` null ` value here in order to
303192use the [ default loop] ( https://github.com/reactphp/event-loop#loop ) . This value
304193SHOULD NOT be given unless you're sure you want to explicitly use a given event
305194loop instance.
306195
307- #### Resolve cancellation
308-
309- You can explicitly ` cancel() ` the resulting timer promise at any time:
196+ The returned promise is implemented in such a way that it can be cancelled
197+ when it is still pending. Cancelling a pending promise will reject its value
198+ with a ` RuntimeException ` and clean up any pending timers.
310199
311200``` php
312201$timer = React\Promise\Timer\resolve(2.0);
313202
314203$timer->cancel();
315204```
316205
317- This will abort the timer and * reject* with a ` RuntimeException ` .
318-
319206### reject()
320207
321- The ` reject($time, LoopInterface $loop = null) ` function can be used to create a new Promise
322- which rejects in ` $time ` seconds with a ` TimeoutException ` .
208+ The ` reject(float $time, ? LoopInterface $loop = null): PromiseInterface<void, TimeoutException|RuntimeException> ` function can be used to
209+ create a new promise which rejects in ` $time ` seconds with a ` TimeoutException ` .
323210
324211``` php
325212React\Promise\Timer\reject(2.0)->then(null, function (React\Promise\Timer\TimeoutException $e) {
@@ -328,36 +215,35 @@ React\Promise\Timer\reject(2.0)->then(null, function (React\Promise\Timer\Timeou
328215```
329216
330217Internally, the given ` $time ` value will be used to start a timer that will
331- reject the promise once it triggers.
332- This implies that if you pass a really small (or negative) value, it will still
333- start a timer and will thus trigger at the earliest possible time in the future.
218+ reject the promise once it triggers. This implies that if you pass a really
219+ small (or negative) value, it will still start a timer and will thus trigger
220+ at the earliest possible time in the future.
334221
335222This function takes an optional ` LoopInterface|null $loop ` parameter that can be used to
336223pass the event loop instance to use. You can use a ` null ` value here in order to
337224use the [ default loop] ( https://github.com/reactphp/event-loop#loop ) . This value
338225SHOULD NOT be given unless you're sure you want to explicitly use a given event
339226loop instance.
340227
341- This function complements the [ ` resolve() ` ] ( #resolve ) function
342- and can be used as a basic building block for higher-level promise consumers.
343-
344- #### Reject cancellation
345-
346- You can explicitly ` cancel() ` the resulting timer promise at any time:
228+ The returned promise is implemented in such a way that it can be cancelled
229+ when it is still pending. Cancelling a pending promise will reject its value
230+ with a ` RuntimeException ` and clean up any pending timers.
347231
348232``` php
349233$timer = React\Promise\Timer\reject(2.0);
350234
351235$timer->cancel();
352236```
353237
354- This will abort the timer and * reject* with a ` RuntimeException ` .
355-
356238### TimeoutException
357239
358240The ` TimeoutException ` extends PHP's built-in ` RuntimeException ` .
359241
360- The ` getTimeout() ` method can be used to get the timeout value in seconds.
242+
243+ #### getTimeout()
244+
245+ The ` getTimeout(): float ` method can be used to
246+ get the timeout value in seconds.
361247
362248## Install
363249
0 commit comments