Skip to content

Commit 90a9edf

Browse files
committed
feat: Handle generator in the asynchronous context.
1 parent a9f27e7 commit 90a9edf

File tree

2 files changed

+26
-4
lines changed

2 files changed

+26
-4
lines changed

src/Core/Async/Async.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,6 @@ public static function throttle(callable $operation, float $interval): callable
499499
$id = ++$counter;
500500
$lastExecution[$id] = 0;
501501

502-
/** @var callable(): T $operation */
503502
return function () use ($operation, $interval, $id, &$lastExecution): PromiseInterface {
504503
$now = Async::getCurrentTime();
505504
$timeSinceLastExecution = $now - $lastExecution[$id];

src/Core/Async/EventLoop.php

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use BadMethodCallException;
88
use Fiber;
9+
use Generator;
910
use SplObjectStorage;
1011
use SplQueue;
1112
use Throwable;
@@ -235,7 +236,7 @@ public function setInterval(callable $callback, float $interval): int
235236
/**
236237
* Cancel a scheduled timer.
237238
*
238-
* @param int $timerId The timer ID returned by setTimeout or setInterval
239+
* @param int $timerId The timer's ID returned by setTimeout or setInterval
239240
* @return void
240241
*/
241242
public function clearTimer(int $timerId): void
@@ -268,7 +269,29 @@ public function async(callable $callable, ?CancellationTokenInterface $cancellat
268269
$cancellationToken?->throwIfCancellationRequested();
269270

270271
$result = $callable();
271-
$deferred->resolve($result);
272+
273+
if ($result instanceof Generator) {
274+
$value = null;
275+
while ($result->valid()) {
276+
$yielded = $result->current();
277+
278+
// If the yielded value is a Fiber, resume it
279+
if ($yielded instanceof Fiber) {
280+
$value = $yielded->isTerminated()
281+
? $yielded->getReturn()
282+
: ($yielded->isSuspended() ? $yielded->resume() : $yielded->start());
283+
} else {
284+
$value = $yielded;
285+
}
286+
287+
EventLoop::getInstance()->yield();
288+
$result->next();
289+
}
290+
291+
$deferred->resolve($result->getReturn() ?? $value ?? null);
292+
} else {
293+
$deferred->resolve($result);
294+
}
272295
} catch (Throwable $e) {
273296
$deferred->reject($e);
274297
}
@@ -281,7 +304,7 @@ public function async(callable $callable, ?CancellationTokenInterface $cancellat
281304
'startTime' => $this->getCurrentTime()
282305
];
283306

284-
// Set up cancellation if token is provided
307+
// Set up cancellation if a token is provided
285308
$cancellationToken?->register(function () use ($fiber, $deferred): void {
286309
if (isset($this->fibers[$fiber])) {
287310
try {

0 commit comments

Comments
 (0)