[ Index ]

PHP Cross Reference of phpBB-3.3.5-deutsch

title

Body

[close]

/vendor/guzzlehttp/promises/ -> README.md (source)

   1  # Guzzle Promises
   2  
   3  [Promises/A+](https://promisesaplus.com/) implementation that handles promise
   4  chaining and resolution iteratively, allowing for "infinite" promise chaining
   5  while keeping the stack size constant. Read [this blog post](https://blog.domenic.me/youre-missing-the-point-of-promises/)
   6  for a general introduction to promises.
   7  
   8  - [Features](#features)
   9  - [Quick start](#quick-start)
  10  - [Synchronous wait](#synchronous-wait)
  11  - [Cancellation](#cancellation)
  12  - [API](#api)
  13    - [Promise](#promise)
  14    - [FulfilledPromise](#fulfilledpromise)
  15    - [RejectedPromise](#rejectedpromise)
  16  - [Promise interop](#promise-interop)
  17  - [Implementation notes](#implementation-notes)
  18  
  19  
  20  # Features
  21  
  22  - [Promises/A+](https://promisesaplus.com/) implementation.
  23  - Promise resolution and chaining is handled iteratively, allowing for
  24    "infinite" promise chaining.
  25  - Promises have a synchronous `wait` method.
  26  - Promises can be cancelled.
  27  - Works with any object that has a `then` function.
  28  - C# style async/await coroutine promises using
  29    `GuzzleHttp\Promise\Coroutine::of()`.
  30  
  31  
  32  # Quick start
  33  
  34  A *promise* represents the eventual result of an asynchronous operation. The
  35  primary way of interacting with a promise is through its `then` method, which
  36  registers callbacks to receive either a promise's eventual value or the reason
  37  why the promise cannot be fulfilled.
  38  
  39  
  40  ## Callbacks
  41  
  42  Callbacks are registered with the `then` method by providing an optional 
  43  `$onFulfilled` followed by an optional `$onRejected` function.
  44  
  45  
  46  ```php
  47  use GuzzleHttp\Promise\Promise;
  48  
  49  $promise = new Promise();
  50  $promise->then(
  51      // $onFulfilled
  52      function ($value) {
  53          echo 'The promise was fulfilled.';
  54      },
  55      // $onRejected
  56      function ($reason) {
  57          echo 'The promise was rejected.';
  58      }
  59  );
  60  ```
  61  
  62  *Resolving* a promise means that you either fulfill a promise with a *value* or
  63  reject a promise with a *reason*. Resolving a promises triggers callbacks
  64  registered with the promises's `then` method. These callbacks are triggered
  65  only once and in the order in which they were added.
  66  
  67  
  68  ## Resolving a promise
  69  
  70  Promises are fulfilled using the `resolve($value)` method. Resolving a promise
  71  with any value other than a `GuzzleHttp\Promise\RejectedPromise` will trigger
  72  all of the onFulfilled callbacks (resolving a promise with a rejected promise
  73  will reject the promise and trigger the `$onRejected` callbacks).
  74  
  75  ```php
  76  use GuzzleHttp\Promise\Promise;
  77  
  78  $promise = new Promise();
  79  $promise
  80      ->then(function ($value) {
  81          // Return a value and don't break the chain
  82          return "Hello, " . $value;
  83      })
  84      // This then is executed after the first then and receives the value
  85      // returned from the first then.
  86      ->then(function ($value) {
  87          echo $value;
  88      });
  89  
  90  // Resolving the promise triggers the $onFulfilled callbacks and outputs
  91  // "Hello, reader."
  92  $promise->resolve('reader.');
  93  ```
  94  
  95  
  96  ## Promise forwarding
  97  
  98  Promises can be chained one after the other. Each then in the chain is a new
  99  promise. The return value of a promise is what's forwarded to the next
 100  promise in the chain. Returning a promise in a `then` callback will cause the
 101  subsequent promises in the chain to only be fulfilled when the returned promise
 102  has been fulfilled. The next promise in the chain will be invoked with the
 103  resolved value of the promise.
 104  
 105  ```php
 106  use GuzzleHttp\Promise\Promise;
 107  
 108  $promise = new Promise();
 109  $nextPromise = new Promise();
 110  
 111  $promise
 112      ->then(function ($value) use ($nextPromise) {
 113          echo $value;
 114          return $nextPromise;
 115      })
 116      ->then(function ($value) {
 117          echo $value;
 118      });
 119  
 120  // Triggers the first callback and outputs "A"
 121  $promise->resolve('A');
 122  // Triggers the second callback and outputs "B"
 123  $nextPromise->resolve('B');
 124  ```
 125  
 126  ## Promise rejection
 127  
 128  When a promise is rejected, the `$onRejected` callbacks are invoked with the
 129  rejection reason.
 130  
 131  ```php
 132  use GuzzleHttp\Promise\Promise;
 133  
 134  $promise = new Promise();
 135  $promise->then(null, function ($reason) {
 136      echo $reason;
 137  });
 138  
 139  $promise->reject('Error!');
 140  // Outputs "Error!"
 141  ```
 142  
 143  ## Rejection forwarding
 144  
 145  If an exception is thrown in an `$onRejected` callback, subsequent
 146  `$onRejected` callbacks are invoked with the thrown exception as the reason.
 147  
 148  ```php
 149  use GuzzleHttp\Promise\Promise;
 150  
 151  $promise = new Promise();
 152  $promise->then(null, function ($reason) {
 153      throw new Exception($reason);
 154  })->then(null, function ($reason) {
 155      assert($reason->getMessage() === 'Error!');
 156  });
 157  
 158  $promise->reject('Error!');
 159  ```
 160  
 161  You can also forward a rejection down the promise chain by returning a
 162  `GuzzleHttp\Promise\RejectedPromise` in either an `$onFulfilled` or
 163  `$onRejected` callback.
 164  
 165  ```php
 166  use GuzzleHttp\Promise\Promise;
 167  use GuzzleHttp\Promise\RejectedPromise;
 168  
 169  $promise = new Promise();
 170  $promise->then(null, function ($reason) {
 171      return new RejectedPromise($reason);
 172  })->then(null, function ($reason) {
 173      assert($reason === 'Error!');
 174  });
 175  
 176  $promise->reject('Error!');
 177  ```
 178  
 179  If an exception is not thrown in a `$onRejected` callback and the callback
 180  does not return a rejected promise, downstream `$onFulfilled` callbacks are
 181  invoked using the value returned from the `$onRejected` callback.
 182  
 183  ```php
 184  use GuzzleHttp\Promise\Promise;
 185  
 186  $promise = new Promise();
 187  $promise
 188      ->then(null, function ($reason) {
 189          return "It's ok";
 190      })
 191      ->then(function ($value) {
 192          assert($value === "It's ok");
 193      });
 194  
 195  $promise->reject('Error!');
 196  ```
 197  
 198  # Synchronous wait
 199  
 200  You can synchronously force promises to complete using a promise's `wait`
 201  method. When creating a promise, you can provide a wait function that is used
 202  to synchronously force a promise to complete. When a wait function is invoked
 203  it is expected to deliver a value to the promise or reject the promise. If the
 204  wait function does not deliver a value, then an exception is thrown. The wait
 205  function provided to a promise constructor is invoked when the `wait` function
 206  of the promise is called.
 207  
 208  ```php
 209  $promise = new Promise(function () use (&$promise) {
 210      $promise->resolve('foo');
 211  });
 212  
 213  // Calling wait will return the value of the promise.
 214  echo $promise->wait(); // outputs "foo"
 215  ```
 216  
 217  If an exception is encountered while invoking the wait function of a promise,
 218  the promise is rejected with the exception and the exception is thrown.
 219  
 220  ```php
 221  $promise = new Promise(function () use (&$promise) {
 222      throw new Exception('foo');
 223  });
 224  
 225  $promise->wait(); // throws the exception.
 226  ```
 227  
 228  Calling `wait` on a promise that has been fulfilled will not trigger the wait
 229  function. It will simply return the previously resolved value.
 230  
 231  ```php
 232  $promise = new Promise(function () { die('this is not called!'); });
 233  $promise->resolve('foo');
 234  echo $promise->wait(); // outputs "foo"
 235  ```
 236  
 237  Calling `wait` on a promise that has been rejected will throw an exception. If
 238  the rejection reason is an instance of `\Exception` the reason is thrown.
 239  Otherwise, a `GuzzleHttp\Promise\RejectionException` is thrown and the reason
 240  can be obtained by calling the `getReason` method of the exception.
 241  
 242  ```php
 243  $promise = new Promise();
 244  $promise->reject('foo');
 245  $promise->wait();
 246  ```
 247  
 248  > PHP Fatal error:  Uncaught exception 'GuzzleHttp\Promise\RejectionException' with message 'The promise was rejected with value: foo'
 249  
 250  
 251  ## Unwrapping a promise
 252  
 253  When synchronously waiting on a promise, you are joining the state of the
 254  promise into the current state of execution (i.e., return the value of the
 255  promise if it was fulfilled or throw an exception if it was rejected). This is
 256  called "unwrapping" the promise. Waiting on a promise will by default unwrap
 257  the promise state.
 258  
 259  You can force a promise to resolve and *not* unwrap the state of the promise
 260  by passing `false` to the first argument of the `wait` function:
 261  
 262  ```php
 263  $promise = new Promise();
 264  $promise->reject('foo');
 265  // This will not throw an exception. It simply ensures the promise has
 266  // been resolved.
 267  $promise->wait(false);
 268  ```
 269  
 270  When unwrapping a promise, the resolved value of the promise will be waited
 271  upon until the unwrapped value is not a promise. This means that if you resolve
 272  promise A with a promise B and unwrap promise A, the value returned by the
 273  wait function will be the value delivered to promise B.
 274  
 275  **Note**: when you do not unwrap the promise, no value is returned.
 276  
 277  
 278  # Cancellation
 279  
 280  You can cancel a promise that has not yet been fulfilled using the `cancel()`
 281  method of a promise. When creating a promise you can provide an optional
 282  cancel function that when invoked cancels the action of computing a resolution
 283  of the promise.
 284  
 285  
 286  # API
 287  
 288  
 289  ## Promise
 290  
 291  When creating a promise object, you can provide an optional `$waitFn` and
 292  `$cancelFn`. `$waitFn` is a function that is invoked with no arguments and is
 293  expected to resolve the promise. `$cancelFn` is a function with no arguments
 294  that is expected to cancel the computation of a promise. It is invoked when the
 295  `cancel()` method of a promise is called.
 296  
 297  ```php
 298  use GuzzleHttp\Promise\Promise;
 299  
 300  $promise = new Promise(
 301      function () use (&$promise) {
 302          $promise->resolve('waited');
 303      },
 304      function () {
 305          // do something that will cancel the promise computation (e.g., close
 306          // a socket, cancel a database query, etc...)
 307      }
 308  );
 309  
 310  assert('waited' === $promise->wait());
 311  ```
 312  
 313  A promise has the following methods:
 314  
 315  - `then(callable $onFulfilled, callable $onRejected) : PromiseInterface`
 316    
 317    Appends fulfillment and rejection handlers to the promise, and returns a new promise resolving to the return value of the called handler.
 318  
 319  - `otherwise(callable $onRejected) : PromiseInterface`
 320    
 321    Appends a rejection handler callback to the promise, and returns a new promise resolving to the return value of the callback if it is called, or to its original fulfillment value if the promise is instead fulfilled.
 322  
 323  - `wait($unwrap = true) : mixed`
 324  
 325    Synchronously waits on the promise to complete.
 326    
 327    `$unwrap` controls whether or not the value of the promise is returned for a
 328    fulfilled promise or if an exception is thrown if the promise is rejected.
 329    This is set to `true` by default.
 330  
 331  - `cancel()`
 332  
 333    Attempts to cancel the promise if possible. The promise being cancelled and
 334    the parent most ancestor that has not yet been resolved will also be
 335    cancelled. Any promises waiting on the cancelled promise to resolve will also
 336    be cancelled.
 337  
 338  - `getState() : string`
 339  
 340    Returns the state of the promise. One of `pending`, `fulfilled`, or
 341    `rejected`.
 342  
 343  - `resolve($value)`
 344  
 345    Fulfills the promise with the given `$value`.
 346  
 347  - `reject($reason)`
 348  
 349    Rejects the promise with the given `$reason`.
 350  
 351  
 352  ## FulfilledPromise
 353  
 354  A fulfilled promise can be created to represent a promise that has been
 355  fulfilled.
 356  
 357  ```php
 358  use GuzzleHttp\Promise\FulfilledPromise;
 359  
 360  $promise = new FulfilledPromise('value');
 361  
 362  // Fulfilled callbacks are immediately invoked.
 363  $promise->then(function ($value) {
 364      echo $value;
 365  });
 366  ```
 367  
 368  
 369  ## RejectedPromise
 370  
 371  A rejected promise can be created to represent a promise that has been
 372  rejected.
 373  
 374  ```php
 375  use GuzzleHttp\Promise\RejectedPromise;
 376  
 377  $promise = new RejectedPromise('Error');
 378  
 379  // Rejected callbacks are immediately invoked.
 380  $promise->then(null, function ($reason) {
 381      echo $reason;
 382  });
 383  ```
 384  
 385  
 386  # Promise interop
 387  
 388  This library works with foreign promises that have a `then` method. This means
 389  you can use Guzzle promises with [React promises](https://github.com/reactphp/promise)
 390  for example. When a foreign promise is returned inside of a then method
 391  callback, promise resolution will occur recursively.
 392  
 393  ```php
 394  // Create a React promise
 395  $deferred = new React\Promise\Deferred();
 396  $reactPromise = $deferred->promise();
 397  
 398  // Create a Guzzle promise that is fulfilled with a React promise.
 399  $guzzlePromise = new GuzzleHttp\Promise\Promise();
 400  $guzzlePromise->then(function ($value) use ($reactPromise) {
 401      // Do something something with the value...
 402      // Return the React promise
 403      return $reactPromise;
 404  });
 405  ```
 406  
 407  Please note that wait and cancel chaining is no longer possible when forwarding
 408  a foreign promise. You will need to wrap a third-party promise with a Guzzle
 409  promise in order to utilize wait and cancel functions with foreign promises.
 410  
 411  
 412  ## Event Loop Integration
 413  
 414  In order to keep the stack size constant, Guzzle promises are resolved
 415  asynchronously using a task queue. When waiting on promises synchronously, the
 416  task queue will be automatically run to ensure that the blocking promise and
 417  any forwarded promises are resolved. When using promises asynchronously in an
 418  event loop, you will need to run the task queue on each tick of the loop. If
 419  you do not run the task queue, then promises will not be resolved.
 420  
 421  You can run the task queue using the `run()` method of the global task queue
 422  instance.
 423  
 424  ```php
 425  // Get the global task queue
 426  $queue = GuzzleHttp\Promise\Utils::queue();
 427  $queue->run();
 428  ```
 429  
 430  For example, you could use Guzzle promises with React using a periodic timer:
 431  
 432  ```php
 433  $loop = React\EventLoop\Factory::create();
 434  $loop->addPeriodicTimer(0, [$queue, 'run']);
 435  ```
 436  
 437  *TODO*: Perhaps adding a `futureTick()` on each tick would be faster?
 438  
 439  
 440  # Implementation notes
 441  
 442  
 443  ## Promise resolution and chaining is handled iteratively
 444  
 445  By shuffling pending handlers from one owner to another, promises are
 446  resolved iteratively, allowing for "infinite" then chaining.
 447  
 448  ```php
 449  <?php
 450  require  'vendor/autoload.php';
 451  
 452  use GuzzleHttp\Promise\Promise;
 453  
 454  $parent = new Promise();
 455  $p = $parent;
 456  
 457  for ($i = 0; $i < 1000; $i++) {
 458      $p = $p->then(function ($v) {
 459          // The stack size remains constant (a good thing)
 460          echo xdebug_get_stack_depth() . ', ';
 461          return $v + 1;
 462      });
 463  }
 464  
 465  $parent->resolve(0);
 466  var_dump($p->wait()); // int(1000)
 467  
 468  ```
 469  
 470  When a promise is fulfilled or rejected with a non-promise value, the promise
 471  then takes ownership of the handlers of each child promise and delivers values
 472  down the chain without using recursion.
 473  
 474  When a promise is resolved with another promise, the original promise transfers
 475  all of its pending handlers to the new promise. When the new promise is
 476  eventually resolved, all of the pending handlers are delivered the forwarded
 477  value.
 478  
 479  
 480  ## A promise is the deferred.
 481  
 482  Some promise libraries implement promises using a deferred object to represent
 483  a computation and a promise object to represent the delivery of the result of
 484  the computation. This is a nice separation of computation and delivery because
 485  consumers of the promise cannot modify the value that will be eventually
 486  delivered.
 487  
 488  One side effect of being able to implement promise resolution and chaining
 489  iteratively is that you need to be able for one promise to reach into the state
 490  of another promise to shuffle around ownership of handlers. In order to achieve
 491  this without making the handlers of a promise publicly mutable, a promise is
 492  also the deferred value, allowing promises of the same parent class to reach
 493  into and modify the private properties of promises of the same type. While this
 494  does allow consumers of the value to modify the resolution or rejection of the
 495  deferred, it is a small price to pay for keeping the stack size constant.
 496  
 497  ```php
 498  $promise = new Promise();
 499  $promise->then(function ($value) { echo $value; });
 500  // The promise is the deferred value, so you can deliver a value to it.
 501  $promise->resolve('foo');
 502  // prints "foo"
 503  ```
 504  
 505  
 506  ## Upgrading from Function API
 507  
 508  A static API was first introduced in 1.4.0, in order to mitigate problems with functions conflicting between global and local copies of the package. The function API will be removed in 2.0.0. A migration table has been provided here for your convenience:
 509  
 510  | Original Function | Replacement Method |
 511  |----------------|----------------|
 512  | `queue` | `Utils::queue` |
 513  | `task` | `Utils::task` |
 514  | `promise_for` | `Create::promiseFor` |
 515  | `rejection_for` | `Create::rejectionFor` |
 516  | `exception_for` | `Create::exceptionFor` |
 517  | `iter_for` | `Create::iterFor` |
 518  | `inspect` | `Utils::inspect` |
 519  | `inspect_all` | `Utils::inspectAll` |
 520  | `unwrap` | `Utils::unwrap` |
 521  | `all` | `Utils::all` |
 522  | `some` | `Utils::some` |
 523  | `any` | `Utils::any` |
 524  | `settle` | `Utils::settle` |
 525  | `each` | `Each::of` |
 526  | `each_limit` | `Each::ofLimit` |
 527  | `each_limit_all` | `Each::ofLimitAll` |
 528  | `!is_fulfilled` | `Is::pending` |
 529  | `is_fulfilled` | `Is::fulfilled` |
 530  | `is_rejected` | `Is::rejected` |
 531  | `is_settled` | `Is::settled` |
 532  | `coroutine` | `Coroutine::of` |


Generated: Mon Oct 4 17:42:11 2021 Cross-referenced by PHPXref 0.7.1