|
4 | 4 |
|
5 | 5 | use React\EventLoop\Loop;
|
6 | 6 | use React\Promise\Deferred;
|
| 7 | +use React\Promise\Promise; |
7 | 8 | use React\Promise\PromiseInterface;
|
8 | 9 |
|
9 | 10 | /**
|
@@ -98,6 +99,85 @@ function ($error) use (&$exception, &$rejected, &$wait, &$loopStarted) {
|
98 | 99 | return $resolved;
|
99 | 100 | }
|
100 | 101 |
|
| 102 | +/** |
| 103 | + * Delay program execution for duration given in `$seconds`. |
| 104 | + * |
| 105 | + * ```php |
| 106 | + * React\Async\delay($seconds); |
| 107 | + * ``` |
| 108 | + * |
| 109 | + * This function will only return after the given number of `$seconds` have |
| 110 | + * elapsed. If there are no other events attached to this loop, it will behave |
| 111 | + * similar to PHP's [`sleep()` function](https://www.php.net/manual/en/function.sleep.php). |
| 112 | + * |
| 113 | + * ```php |
| 114 | + * echo 'a'; |
| 115 | + * React\Async\delay(1.0); |
| 116 | + * echo 'b'; |
| 117 | + * |
| 118 | + * // prints "a" at t=0.0s |
| 119 | + * // prints "b" at t=1.0s |
| 120 | + * ``` |
| 121 | + * |
| 122 | + * Unlike PHP's [`sleep()` function](https://www.php.net/manual/en/function.sleep.php), |
| 123 | + * this function may not necessarily halt execution of the entire process thread. |
| 124 | + * Instead, it allows the event loop to run any other events attached to the |
| 125 | + * same loop until the delay returns: |
| 126 | + * |
| 127 | + * ```php |
| 128 | + * echo 'a'; |
| 129 | + * Loop::addTimer(1.0, function () { |
| 130 | + * echo 'b'; |
| 131 | + * }); |
| 132 | + * React\Async\delay(3.0); |
| 133 | + * echo 'c'; |
| 134 | + * |
| 135 | + * // prints "a" at t=0.0s |
| 136 | + * // prints "b" at t=1.0s |
| 137 | + * // prints "c" at t=3.0s |
| 138 | + * ``` |
| 139 | + * |
| 140 | + * This behavior is especially useful if you want to delay the program execution |
| 141 | + * of a particular routine, such as when building a simple polling or retry |
| 142 | + * mechanism: |
| 143 | + * |
| 144 | + * ```php |
| 145 | + * try { |
| 146 | + * something(); |
| 147 | + * } catch (Exception $e) { |
| 148 | + * // in case of error, retry after a short delay |
| 149 | + * React\Async\delay(1.0); |
| 150 | + * something(); |
| 151 | + * } |
| 152 | + * ``` |
| 153 | + * |
| 154 | + * Because this function only returns after some time has passed, it can be |
| 155 | + * considered *blocking* from the perspective of the calling code. While the |
| 156 | + * delay is running, this function will assume control over the event loop. |
| 157 | + * Internally, it will `run()` the [default loop](https://github.com/reactphp/event-loop#loop) |
| 158 | + * until the delay returns and then calls `stop()` to terminate execution of the |
| 159 | + * loop. This means this function is more suited for short-lived promise executions |
| 160 | + * when using promise-based APIs is not feasible. For long-running applications, |
| 161 | + * using promise-based APIs by leveraging chained `then()` calls is usually preferable. |
| 162 | + * |
| 163 | + * Internally, the `$seconds` argument will be used as a timer for the loop so that |
| 164 | + * it keeps running until this timer triggers. This implies that if you pass a |
| 165 | + * really small (or negative) value, it will still start a timer and will thus |
| 166 | + * trigger at the earliest possible time in the future. |
| 167 | + * |
| 168 | + * @param float $seconds |
| 169 | + * @return void |
| 170 | + * @uses await() |
| 171 | + */ |
| 172 | +function delay($seconds) |
| 173 | +{ |
| 174 | + await(new Promise(function ($resolve) use ($seconds) { |
| 175 | + Loop::addTimer($seconds, function () use ($resolve) { |
| 176 | + $resolve(null); |
| 177 | + }); |
| 178 | + })); |
| 179 | +} |
| 180 | + |
101 | 181 | /**
|
102 | 182 | * @param array<callable():PromiseInterface<mixed,Exception>> $tasks
|
103 | 183 | * @return PromiseInterface<array<mixed>,Exception>
|
|
0 commit comments