Skip to content

Commit 4933a84

Browse files
committed
Add consistent API documentation for all functions
1 parent 48088fa commit 4933a84

File tree

3 files changed

+239
-173
lines changed

3 files changed

+239
-173
lines changed

README.md

Lines changed: 54 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,8 @@ 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)
2114
* [getTimeout()](#gettimeout)
2215
* [Install](#install)
@@ -53,18 +46,25 @@ Timer\timeout(…);
5346
### timeout()
5447

5548
The `timeout(PromiseInterface<mixed, Exception|mixed> $promise, float $time, ?LoopInterface $loop = null): PromiseInterface<mixed, TimeoutException|Exception|mixed>` function can be used to
56-
*cancel* operations that take *too long*.
57-
You need to pass in an input `$promise` that represents a pending operation and timeout parameters.
58-
It returns a new `Promise` with the following resolution behavior:
49+
cancel operations that take *too long*.
5950

60-
* If the input `$promise` resolves before `$time` seconds, resolve the resulting promise with its fulfillment value.
61-
* If the input `$promise` rejects before `$time` seconds, reject the resulting promise with its rejection value.
62-
* 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).
6363

6464
Internally, the given `$time` value will be used to start a timer that will
65-
*cancel* the pending operation once it triggers.
66-
This implies that if you pass a really small (or negative) value, it will still
67-
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.
6868

6969
If the input `$promise` is already settled, then the resulting promise will
7070
resolve or reject immediately without starting a timer at all.
@@ -118,151 +118,38 @@ React\Promise\Timer\timeout($promise, 10.0)
118118
;
119119
```
120120

121-
#### Timeout cancellation
122-
123-
As discussed above, the [`timeout()`](#timeout) function will *cancel* the
124-
underlying operation if it takes *too long*.
125-
This means that you can be sure the resulting promise will then be rejected
126-
with a [`TimeoutException`](#timeoutexception).
127-
128-
However, what happens to the underlying input `$promise` is a bit more tricky:
129-
Once the timer fires, we will try to call
130-
[`$promise->cancel()`](https://github.com/reactphp/promise#cancellablepromiseinterfacecancel)
131-
on the input `$promise` which in turn invokes its [cancellation handler](#cancellation-handler).
132-
133-
This means that it's actually up the input `$promise` to handle
134-
[cancellation support](https://github.com/reactphp/promise#cancellablepromiseinterface).
135-
136-
* A common use case involves cleaning up any resources like open network sockets or
137-
file handles or terminating external processes or timers.
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.
138127

139-
* If the given input `$promise` does not support cancellation, then this is a NO-OP.
140-
This means that while the resulting promise will still be rejected, the underlying
141-
input `$promise` 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.
142130

143-
See the following chapter for more details on the cancellation handler.
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
144135

145-
#### Cancellation handler
146-
147-
For example, an implementation for the above operation could look like this:
148-
149-
```php
150-
function accessSomeRemoteResource()
151-
{
152-
return new Promise(
153-
function ($resolve, $reject) use (&$socket) {
154-
// this will be called once the promise is created
155-
// a common use case involves opening any resources and eventually resolving
156-
$socket = createSocket();
157-
$socket->on('data', function ($data) use ($resolve) {
158-
$resolve($data);
159-
});
160-
},
161-
function ($resolve, $reject) use (&$socket) {
162-
// this will be called once calling `cancel()` on this promise
163-
// a common use case involves cleaning any resources and then rejecting
164-
$socket->close();
165-
$reject(new \RuntimeException('Operation cancelled'));
166-
}
167-
);
168-
}
169-
```
170-
171-
In this example, calling `$promise->cancel()` will invoke the registered cancellation
172-
handler which then closes the network socket and rejects the `Promise` instance.
173-
174-
If no cancellation handler is passed to the `Promise` constructor, then invoking
175-
its `cancel()` method it is effectively a NO-OP.
176-
This means that it may still be pending and can hence continue consuming resources.
177-
178-
For more details on the promise cancellation, please refer to the
179-
[Promise documentation](https://github.com/reactphp/promise#cancellablepromiseinterface).
180-
181-
#### Input cancellation
182-
183-
Irrespective of the timeout handling, you can also explicitly `cancel()` the
184-
input `$promise` at any time.
185-
This means that the `timeout()` handling does not affect cancellation of the
186-
input `$promise`, as demonstrated in the following example:
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.
187140

188141
```php
189142
$promise = accessSomeRemoteResource();
190143
$timeout = React\Promise\Timer\timeout($promise, 10.0);
191144

192-
$promise->cancel();
193-
```
194-
195-
The registered [cancellation handler](#cancellation-handler) is responsible for
196-
handling the `cancel()` call:
197-
198-
* A described above, a common use involves resource cleanup and will then *reject*
199-
the `Promise`.
200-
If the input `$promise` is being rejected, then the timeout will be aborted
201-
and the resulting promise will also be rejected.
202-
* If the input `$promise` is still pending, then the timout will continue
203-
running until the timer expires.
204-
The same happens if the input `$promise` does not register a
205-
[cancellation handler](#cancellation-handler).
206-
207-
#### Output cancellation
208-
209-
Similarily, you can also explicitly `cancel()` the resulting promise like this:
210-
211-
```php
212-
$promise = accessSomeRemoteResource();
213-
$timeout = React\Promise\Timer\timeout($promise, 10.0);
214-
215-
$timeout->cancel();
216-
```
217-
218-
Note how this looks very similar to the above [input cancellation](#input-cancellation)
219-
example. Accordingly, it also behaves very similar.
220-
221-
Calling `cancel()` on the resulting promise will merely try
222-
to `cancel()` the input `$promise`.
223-
This means that we do not take over responsibility of the outcome and it's
224-
entirely up to the input `$promise` to handle cancellation support.
225-
226-
The registered [cancellation handler](#cancellation-handler) is responsible for
227-
handling the `cancel()` call:
228-
229-
* As described above, a common use involves resource cleanup and will then *reject*
230-
the `Promise`.
231-
If the input `$promise` is being rejected, then the timeout will be aborted
232-
and the resulting promise will also be rejected.
233-
* If the input `$promise` is still pending, then the timout will continue
234-
running until the timer expires.
235-
The same happens if the input `$promise` does not register a
236-
[cancellation handler](#cancellation-handler).
237-
238-
To re-iterate, note that calling `cancel()` on the resulting promise will merely
239-
try to cancel the input `$promise` only.
240-
It is then up to the cancellation handler of the input promise to settle the promise.
241-
If the input promise is still pending when the timeout occurs, then the normal
242-
[timeout cancellation](#timeout-cancellation) handling will trigger, effectively rejecting
243-
the output promise with a [`TimeoutException`](#timeoutexception).
244-
245-
This is done for consistency with the [timeout cancellation](#timeout-cancellation)
246-
handling and also because it is assumed this is often used like this:
247-
248-
```php
249-
$timeout = React\Promise\Timer\timeout(accessSomeRemoteResource(), 10.0);
250-
251145
$timeout->cancel();
252146
```
253147

254-
As described above, this example works as expected and cleans up any resources
255-
allocated for the input `$promise`.
256-
257-
Note that if the given input `$promise` does not support cancellation, then this
258-
is a NO-OP.
259-
This means that while the resulting promise will still be rejected after the
260-
timeout, the underlying input `$promise` may still be pending and can hence
261-
continue consuming resources.
262-
263-
#### Collections
148+
For more details on the promise cancellation, please refer to the
149+
[Promise documentation](https://github.com/reactphp/promise#cancellablepromiseinterface).
264150

265-
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:
266153

267154
```php
268155
$promises = array(
@@ -271,22 +158,23 @@ $promises = array(
271158
accessSomeRemoteResource()
272159
);
273160

274-
$promise = \React\Promise\all($promises);
161+
$promise = React\Promise\all($promises);
275162

276163
React\Promise\Timer\timeout($promise, 10)->then(function ($values) {
277164
// *all* promises resolved
278165
});
279166
```
280167

281-
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.
282170

283171
For more details on the promise primitives, please refer to the
284172
[Promise documentation](https://github.com/reactphp/promise#functions).
285173

286174
### resolve()
287175

288176
The `resolve(float $time, ?LoopInterface $loop = null): PromiseInterface<float, RuntimeException>` function can be used to
289-
create a new Promise that resolves in `$time` seconds with the `$time` as the fulfillment value.
177+
create a new promise that resolves in `$time` seconds with the `$time` as the fulfillment value.
290178

291179
```php
292180
React\Promise\Timer\resolve(1.5)->then(function ($time) {
@@ -295,32 +183,30 @@ React\Promise\Timer\resolve(1.5)->then(function ($time) {
295183
```
296184

297185
Internally, the given `$time` value will be used to start a timer that will
298-
resolve the promise once it triggers.
299-
This implies that if you pass a really small (or negative) value, it will still
300-
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.
301189

302190
This function takes an optional `LoopInterface|null $loop` parameter that can be used to
303191
pass the event loop instance to use. You can use a `null` value here in order to
304192
use the [default loop](https://github.com/reactphp/event-loop#loop). This value
305193
SHOULD NOT be given unless you're sure you want to explicitly use a given event
306194
loop instance.
307195

308-
#### Resolve cancellation
309-
310-
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.
311199

312200
```php
313201
$timer = React\Promise\Timer\resolve(2.0);
314202

315203
$timer->cancel();
316204
```
317205

318-
This will abort the timer and *reject* with a `RuntimeException`.
319-
320206
### reject()
321207

322-
The `reject(float $time, ?LoopInterface $loop = null): PromiseInterface<TimeoutException, RuntimeException>` function can be used
323-
to create a new Promise which rejects in `$time` seconds with a `TimeoutException`.
208+
The `reject(float $time, ?LoopInterface $loop = null): PromiseInterface<TimeoutException, RuntimeException>` function can be used to
209+
create a new promise which rejects in `$time` seconds with a `TimeoutException`.
324210

325211
```php
326212
React\Promise\Timer\reject(2.0)->then(null, function (React\Promise\Timer\TimeoutException $e) {
@@ -329,31 +215,26 @@ React\Promise\Timer\reject(2.0)->then(null, function (React\Promise\Timer\Timeou
329215
```
330216

331217
Internally, the given `$time` value will be used to start a timer that will
332-
reject the promise once it triggers.
333-
This implies that if you pass a really small (or negative) value, it will still
334-
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.
335221

336222
This function takes an optional `LoopInterface|null $loop` parameter that can be used to
337223
pass the event loop instance to use. You can use a `null` value here in order to
338224
use the [default loop](https://github.com/reactphp/event-loop#loop). This value
339225
SHOULD NOT be given unless you're sure you want to explicitly use a given event
340226
loop instance.
341227

342-
This function complements the [`resolve()`](#resolve) function
343-
and can be used as a basic building block for higher-level promise consumers.
344-
345-
#### Reject cancellation
346-
347-
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.
348231

349232
```php
350233
$timer = React\Promise\Timer\reject(2.0);
351234

352235
$timer->cancel();
353236
```
354237

355-
This will abort the timer and *reject* with a `RuntimeException`.
356-
357238
### TimeoutException
358239

359240
The `TimeoutException` extends PHP's built-in `RuntimeException`.

src/TimeoutException.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ public function __construct($timeout, $message = null, $code = null, $previous =
2323
}
2424

2525
/**
26+
* Get the timeout value in seconds.
27+
*
2628
* @return float
2729
*/
2830
public function getTimeout()

0 commit comments

Comments
 (0)