13 private static self $instance;
14 private ?Throwable $lastException =
null;
15 private bool $isScheduled =
false;
16 private bool $isInBackground =
false;
20 private array $promises = [];
21 private array $promisesInProgress = [];
22 private array $completedPromises = [];
23 private array $keysToRemove = [];
25 private function __construct()
31 self::$instance ??=
new self();
33 return self::$instance;
41 $this->completedPromises[$promise->id] = $promise;
46 $this->promises[$promise->id] = $promise;
52 $this->keysToRemove[] = $promise->id;
53 $this->completedPromises[$promise->id] = $promise;
61 if ($target && $target->getState() !== State::Pending)
63 return $target->getResult();
68 $result = $this->processQueue($target);
69 $this->processLastException();
84 while (($promise = current($this->promises)) !==
false)
86 $this->processPromise($promise);
88 if ($target && isset($this->completedPromises[$target->id]))
90 return $this->completedPromises[$target->id]->getResult();
93 next($this->promises);
98 $this->lastException =
new SystemException(
'The target promise was not fulfilled');
107 private function processLastException(): void
109 if (!$this->lastException)
114 $exception = $this->lastException;
115 $this->lastException =
null;
120 private function processPromise(Promise $promise): void
122 if (isset($this->promisesInProgress[$promise->id]))
127 $this->promisesInProgress[$promise->id] = $promise;
133 catch (Throwable $exception)
135 $this->lastException = $exception;
138 unset($this->promisesInProgress[$promise->id]);
141 private function runInBackground(): void
143 $this->isInBackground =
true;
145 $this->isScheduled =
false;
148 private function schedule(): void
150 if ($this->isScheduled)
156 $this->isScheduled =
true;
159 private function cleanQueue(): void
161 foreach ($this->keysToRemove as
$key)
163 unset($this->promises[
$key]);
166 $this->keysToRemove = [];