[ Index ]

PHP Cross Reference of phpBB-3.2.11-deutsch

title

Body

[close]

/vendor/react/promise/src/ -> Promise.php (source)

   1  <?php
   2  
   3  namespace React\Promise;
   4  
   5  class Promise implements ExtendedPromiseInterface, CancellablePromiseInterface
   6  {
   7      private $canceller;
   8      private $result;
   9  
  10      private $handlers = [];
  11      private $progressHandlers = [];
  12  
  13      private $requiredCancelRequests = 0;
  14      private $cancelRequests = 0;
  15  
  16      public function __construct(callable $resolver, callable $canceller = null)
  17      {
  18          $this->canceller = $canceller;
  19  
  20          // Explicitly overwrite arguments with null values before invoking
  21          // resolver function. This ensure that these arguments do not show up
  22          // in the stack trace in PHP 7+ only.
  23          $cb = $resolver;
  24          $resolver = $canceller = null;
  25          $this->call($cb);
  26      }
  27  
  28      public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
  29      {
  30          if (null !== $this->result) {
  31              return $this->result->then($onFulfilled, $onRejected, $onProgress);
  32          }
  33  
  34          if (null === $this->canceller) {
  35              return new static($this->resolver($onFulfilled, $onRejected, $onProgress));
  36          }
  37  
  38          // This promise has a canceller, so we create a new child promise which
  39          // has a canceller that invokes the parent canceller if all other
  40          // followers are also cancelled. We keep a reference to this promise
  41          // instance for the static canceller function and clear this to avoid
  42          // keeping a cyclic reference between parent and follower.
  43          $parent = $this;
  44          ++$parent->requiredCancelRequests;
  45  
  46          return new static(
  47              $this->resolver($onFulfilled, $onRejected, $onProgress),
  48              static function () use (&$parent) {
  49                  if (++$parent->cancelRequests >= $parent->requiredCancelRequests) {
  50                      $parent->cancel();
  51                  }
  52  
  53                  $parent = null;
  54              }
  55          );
  56      }
  57  
  58      public function done(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
  59      {
  60          if (null !== $this->result) {
  61              return $this->result->done($onFulfilled, $onRejected, $onProgress);
  62          }
  63  
  64          $this->handlers[] = static function (ExtendedPromiseInterface $promise) use ($onFulfilled, $onRejected) {
  65              $promise
  66                  ->done($onFulfilled, $onRejected);
  67          };
  68  
  69          if ($onProgress) {
  70              $this->progressHandlers[] = $onProgress;
  71          }
  72      }
  73  
  74      public function otherwise(callable $onRejected)
  75      {
  76          return $this->then(null, static function ($reason) use ($onRejected) {
  77              if (!_checkTypehint($onRejected, $reason)) {
  78                  return new RejectedPromise($reason);
  79              }
  80  
  81              return $onRejected($reason);
  82          });
  83      }
  84  
  85      public function always(callable $onFulfilledOrRejected)
  86      {
  87          return $this->then(static function ($value) use ($onFulfilledOrRejected) {
  88              return resolve($onFulfilledOrRejected())->then(function () use ($value) {
  89                  return $value;
  90              });
  91          }, static function ($reason) use ($onFulfilledOrRejected) {
  92              return resolve($onFulfilledOrRejected())->then(function () use ($reason) {
  93                  return new RejectedPromise($reason);
  94              });
  95          });
  96      }
  97  
  98      public function progress(callable $onProgress)
  99      {
 100          return $this->then(null, null, $onProgress);
 101      }
 102  
 103      public function cancel()
 104      {
 105          if (null === $this->canceller || null !== $this->result) {
 106              return;
 107          }
 108  
 109          $canceller = $this->canceller;
 110          $this->canceller = null;
 111  
 112          $this->call($canceller);
 113      }
 114  
 115      private function resolver(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null)
 116      {
 117          return function ($resolve, $reject, $notify) use ($onFulfilled, $onRejected, $onProgress) {
 118              if ($onProgress) {
 119                  $progressHandler = static function ($update) use ($notify, $onProgress) {
 120                      try {
 121                          $notify($onProgress($update));
 122                      } catch (\Throwable $e) {
 123                          $notify($e);
 124                      } catch (\Exception $e) {
 125                          $notify($e);
 126                      }
 127                  };
 128              } else {
 129                  $progressHandler = $notify;
 130              }
 131  
 132              $this->handlers[] = static function (ExtendedPromiseInterface $promise) use ($onFulfilled, $onRejected, $resolve, $reject, $progressHandler) {
 133                  $promise
 134                      ->then($onFulfilled, $onRejected)
 135                      ->done($resolve, $reject, $progressHandler);
 136              };
 137  
 138              $this->progressHandlers[] = $progressHandler;
 139          };
 140      }
 141  
 142      private function reject($reason = null)
 143      {
 144          if (null !== $this->result) {
 145              return;
 146          }
 147  
 148          $this->settle(reject($reason));
 149      }
 150  
 151      private function settle(ExtendedPromiseInterface $promise)
 152      {
 153          $promise = $this->unwrap($promise);
 154  
 155          if ($promise === $this) {
 156              $promise = new RejectedPromise(
 157                  new \LogicException('Cannot resolve a promise with itself.')
 158              );
 159          }
 160  
 161          $handlers = $this->handlers;
 162  
 163          $this->progressHandlers = $this->handlers = [];
 164          $this->result = $promise;
 165          $this->canceller = null;
 166  
 167          foreach ($handlers as $handler) {
 168              $handler($promise);
 169          }
 170      }
 171  
 172      private function unwrap($promise)
 173      {
 174          $promise = $this->extract($promise);
 175  
 176          while ($promise instanceof self && null !== $promise->result) {
 177              $promise = $this->extract($promise->result);
 178          }
 179  
 180          return $promise;
 181      }
 182  
 183      private function extract($promise)
 184      {
 185          if ($promise instanceof LazyPromise) {
 186              $promise = $promise->promise();
 187          }
 188  
 189          return $promise;
 190      }
 191  
 192      private function call(callable $cb)
 193      {
 194          // Explicitly overwrite argument with null value. This ensure that this
 195          // argument does not show up in the stack trace in PHP 7+ only.
 196          $callback = $cb;
 197          $cb = null;
 198  
 199          // Use reflection to inspect number of arguments expected by this callback.
 200          // We did some careful benchmarking here: Using reflection to avoid unneeded
 201          // function arguments is actually faster than blindly passing them.
 202          // Also, this helps avoiding unnecessary function arguments in the call stack
 203          // if the callback creates an Exception (creating garbage cycles).
 204          if (\is_array($callback)) {
 205              $ref = new \ReflectionMethod($callback[0], $callback[1]);
 206          } elseif (\is_object($callback) && !$callback instanceof \Closure) {
 207              $ref = new \ReflectionMethod($callback, '__invoke');
 208          } else {
 209              $ref = new \ReflectionFunction($callback);
 210          }
 211          $args = $ref->getNumberOfParameters();
 212  
 213          try {
 214              if ($args === 0) {
 215                  $callback();
 216              } else {
 217                  // Keep references to this promise instance for the static resolve/reject functions.
 218                  // By using static callbacks that are not bound to this instance
 219                  // and passing the target promise instance by reference, we can
 220                  // still execute its resolving logic and still clear this
 221                  // reference when settling the promise. This helps avoiding
 222                  // garbage cycles if any callback creates an Exception.
 223                  // These assumptions are covered by the test suite, so if you ever feel like
 224                  // refactoring this, go ahead, any alternative suggestions are welcome!
 225                  $target =& $this;
 226                  $progressHandlers =& $this->progressHandlers;
 227  
 228                  $callback(
 229                      static function ($value = null) use (&$target) {
 230                          if ($target !== null) {
 231                              $target->settle(resolve($value));
 232                              $target = null;
 233                          }
 234                      },
 235                      static function ($reason = null) use (&$target) {
 236                          if ($target !== null) {
 237                              $target->reject($reason);
 238                              $target = null;
 239                          }
 240                      },
 241                      static function ($update = null) use (&$progressHandlers) {
 242                          foreach ($progressHandlers as $handler) {
 243                              $handler($update);
 244                          }
 245                      }
 246                  );
 247              }
 248          } catch (\Throwable $e) {
 249              $target = null;
 250              $this->reject($e);
 251          } catch (\Exception $e) {
 252              $target = null;
 253              $this->reject($e);
 254          }
 255      }
 256  }


Generated: Wed Nov 11 20:33:01 2020 Cross-referenced by PHPXref 0.7.1