Verzeichnisstruktur phpBB-3.3.15


Veröffentlicht
28.08.2024

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

README.md

Zuletzt modifiziert: 02.04.2025, 15:02 - Dateigröße: 17.02 KiB


001  # Guzzle Promises
002   
003  [Promises/A+](https://promisesaplus.com/) implementation that handles promise
004  chaining and resolution iteratively, allowing for "infinite" promise chaining
005  while keeping the stack size constant. Read [this blog post](https://blog.domenic.me/youre-missing-the-point-of-promises/)
006  for a general introduction to promises.
007   
008  - [Features](#features)
009  - [Quick start](#quick-start)
010  - [Synchronous wait](#synchronous-wait)
011  - [Cancellation](#cancellation)
012  - [API](#api)
013    - [Promise](#promise)
014    - [FulfilledPromise](#fulfilledpromise)
015    - [RejectedPromise](#rejectedpromise)
016  - [Promise interop](#promise-interop)
017  - [Implementation notes](#implementation-notes)
018   
019   
020  ## Features
021   
022  - [Promises/A+](https://promisesaplus.com/) implementation.
023  - Promise resolution and chaining is handled iteratively, allowing for
024    "infinite" promise chaining.
025  - Promises have a synchronous `wait` method.
026  - Promises can be cancelled.
027  - Works with any object that has a `then` function.
028  - C# style async/await coroutine promises using
029    `GuzzleHttp\Promise\Coroutine::of()`.
030   
031   
032  ## Quick Start
033   
034  A *promise* represents the eventual result of an asynchronous operation. The
035  primary way of interacting with a promise is through its `then` method, which
036  registers callbacks to receive either a promise's eventual value or the reason
037  why the promise cannot be fulfilled.
038   
039  ### Callbacks
040   
041  Callbacks are registered with the `then` method by providing an optional 
042  `$onFulfilled` followed by an optional `$onRejected` function.
043   
044   
045  ```php
046  use GuzzleHttp\Promise\Promise;
047   
048  $promise = new Promise();
049  $promise->then(
050      // $onFulfilled
051      function ($value) {
052          echo 'The promise was fulfilled.';
053      },
054      // $onRejected
055      function ($reason) {
056          echo 'The promise was rejected.';
057      }
058  );
059  ```
060   
061  *Resolving* a promise means that you either fulfill a promise with a *value* or
062  reject a promise with a *reason*. Resolving a promise triggers callbacks
063  registered with the promise's `then` method. These callbacks are triggered
064  only once and in the order in which they were added.
065   
066  ### Resolving a Promise
067   
068  Promises are fulfilled using the `resolve($value)` method. Resolving a promise
069  with any value other than a `GuzzleHttp\Promise\RejectedPromise` will trigger
070  all of the onFulfilled callbacks (resolving a promise with a rejected promise
071  will reject the promise and trigger the `$onRejected` callbacks).
072   
073  ```php
074  use GuzzleHttp\Promise\Promise;
075   
076  $promise = new Promise();
077  $promise
078      ->then(function ($value) {
079          // Return a value and don't break the chain
080          return "Hello, " . $value;
081      })
082      // This then is executed after the first then and receives the value
083      // returned from the first then.
084      ->then(function ($value) {
085          echo $value;
086      });
087   
088  // Resolving the promise triggers the $onFulfilled callbacks and outputs
089  // "Hello, reader."
090  $promise->resolve('reader.');
091  ```
092   
093  ### Promise Forwarding
094   
095  Promises can be chained one after the other. Each then in the chain is a new
096  promise. The return value of a promise is what's forwarded to the next
097  promise in the chain. Returning a promise in a `then` callback will cause the
098  subsequent promises in the chain to only be fulfilled when the returned promise
099  has been fulfilled. The next promise in the chain will be invoked with the
100  resolved value of the promise.
101   
102  ```php
103  use GuzzleHttp\Promise\Promise;
104   
105  $promise = new Promise();
106  $nextPromise = new Promise();
107   
108  $promise
109      ->then(function ($value) use ($nextPromise) {
110          echo $value;
111          return $nextPromise;
112      })
113      ->then(function ($value) {
114          echo $value;
115      });
116   
117  // Triggers the first callback and outputs "A"
118  $promise->resolve('A');
119  // Triggers the second callback and outputs "B"
120  $nextPromise->resolve('B');
121  ```
122   
123  ### Promise Rejection
124   
125  When a promise is rejected, the `$onRejected` callbacks are invoked with the
126  rejection reason.
127   
128  ```php
129  use GuzzleHttp\Promise\Promise;
130   
131  $promise = new Promise();
132  $promise->then(null, function ($reason) {
133      echo $reason;
134  });
135   
136  $promise->reject('Error!');
137  // Outputs "Error!"
138  ```
139   
140  ### Rejection Forwarding
141   
142  If an exception is thrown in an `$onRejected` callback, subsequent
143  `$onRejected` callbacks are invoked with the thrown exception as the reason.
144   
145  ```php
146  use GuzzleHttp\Promise\Promise;
147   
148  $promise = new Promise();
149  $promise->then(null, function ($reason) {
150      throw new Exception($reason);
151  })->then(null, function ($reason) {
152      assert($reason->getMessage() === 'Error!');
153  });
154   
155  $promise->reject('Error!');
156  ```
157   
158  You can also forward a rejection down the promise chain by returning a
159  `GuzzleHttp\Promise\RejectedPromise` in either an `$onFulfilled` or
160  `$onRejected` callback.
161   
162  ```php
163  use GuzzleHttp\Promise\Promise;
164  use GuzzleHttp\Promise\RejectedPromise;
165   
166  $promise = new Promise();
167  $promise->then(null, function ($reason) {
168      return new RejectedPromise($reason);
169  })->then(null, function ($reason) {
170      assert($reason === 'Error!');
171  });
172   
173  $promise->reject('Error!');
174  ```
175   
176  If an exception is not thrown in a `$onRejected` callback and the callback
177  does not return a rejected promise, downstream `$onFulfilled` callbacks are
178  invoked using the value returned from the `$onRejected` callback.
179   
180  ```php
181  use GuzzleHttp\Promise\Promise;
182   
183  $promise = new Promise();
184  $promise
185      ->then(null, function ($reason) {
186          return "It's ok";
187      })
188      ->then(function ($value) {
189          assert($value === "It's ok");
190      });
191   
192  $promise->reject('Error!');
193  ```
194   
195   
196  ## Synchronous Wait
197   
198  You can synchronously force promises to complete using a promise's `wait`
199  method. When creating a promise, you can provide a wait function that is used
200  to synchronously force a promise to complete. When a wait function is invoked
201  it is expected to deliver a value to the promise or reject the promise. If the
202  wait function does not deliver a value, then an exception is thrown. The wait
203  function provided to a promise constructor is invoked when the `wait` function
204  of the promise is called.
205   
206  ```php
207  $promise = new Promise(function () use (&$promise) {
208      $promise->resolve('foo');
209  });
210   
211  // Calling wait will return the value of the promise.
212  echo $promise->wait(); // outputs "foo"
213  ```
214   
215  If an exception is encountered while invoking the wait function of a promise,
216  the promise is rejected with the exception and the exception is thrown.
217   
218  ```php
219  $promise = new Promise(function () use (&$promise) {
220      throw new Exception('foo');
221  });
222   
223  $promise->wait(); // throws the exception.
224  ```
225   
226  Calling `wait` on a promise that has been fulfilled will not trigger the wait
227  function. It will simply return the previously resolved value.
228   
229  ```php
230  $promise = new Promise(function () { die('this is not called!'); });
231  $promise->resolve('foo');
232  echo $promise->wait(); // outputs "foo"
233  ```
234   
235  Calling `wait` on a promise that has been rejected will throw an exception. If
236  the rejection reason is an instance of `\Exception` the reason is thrown.
237  Otherwise, a `GuzzleHttp\Promise\RejectionException` is thrown and the reason
238  can be obtained by calling the `getReason` method of the exception.
239   
240  ```php
241  $promise = new Promise();
242  $promise->reject('foo');
243  $promise->wait();
244  ```
245   
246  > PHP Fatal error:  Uncaught exception 'GuzzleHttp\Promise\RejectionException' with message 'The promise was rejected with value: foo'
247   
248  ### Unwrapping a Promise
249   
250  When synchronously waiting on a promise, you are joining the state of the
251  promise into the current state of execution (i.e., return the value of the
252  promise if it was fulfilled or throw an exception if it was rejected). This is
253  called "unwrapping" the promise. Waiting on a promise will by default unwrap
254  the promise state.
255   
256  You can force a promise to resolve and *not* unwrap the state of the promise
257  by passing `false` to the first argument of the `wait` function:
258   
259  ```php
260  $promise = new Promise();
261  $promise->reject('foo');
262  // This will not throw an exception. It simply ensures the promise has
263  // been resolved.
264  $promise->wait(false);
265  ```
266   
267  When unwrapping a promise, the resolved value of the promise will be waited
268  upon until the unwrapped value is not a promise. This means that if you resolve
269  promise A with a promise B and unwrap promise A, the value returned by the
270  wait function will be the value delivered to promise B.
271   
272  **Note**: when you do not unwrap the promise, no value is returned.
273   
274   
275  ## Cancellation
276   
277  You can cancel a promise that has not yet been fulfilled using the `cancel()`
278  method of a promise. When creating a promise you can provide an optional
279  cancel function that when invoked cancels the action of computing a resolution
280  of the promise.
281   
282   
283  ## API
284   
285  ### Promise
286   
287  When creating a promise object, you can provide an optional `$waitFn` and
288  `$cancelFn`. `$waitFn` is a function that is invoked with no arguments and is
289  expected to resolve the promise. `$cancelFn` is a function with no arguments
290  that is expected to cancel the computation of a promise. It is invoked when the
291  `cancel()` method of a promise is called.
292   
293  ```php
294  use GuzzleHttp\Promise\Promise;
295   
296  $promise = new Promise(
297      function () use (&$promise) {
298          $promise->resolve('waited');
299      },
300      function () {
301          // do something that will cancel the promise computation (e.g., close
302          // a socket, cancel a database query, etc...)
303      }
304  );
305   
306  assert('waited' === $promise->wait());
307  ```
308   
309  A promise has the following methods:
310   
311  - `then(callable $onFulfilled, callable $onRejected) : PromiseInterface`
312    
313    Appends fulfillment and rejection handlers to the promise, and returns a new promise resolving to the return value of the called handler.
314   
315  - `otherwise(callable $onRejected) : PromiseInterface`
316    
317    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.
318   
319  - `wait($unwrap = true) : mixed`
320   
321    Synchronously waits on the promise to complete.
322    
323    `$unwrap` controls whether or not the value of the promise is returned for a
324    fulfilled promise or if an exception is thrown if the promise is rejected.
325    This is set to `true` by default.
326   
327  - `cancel()`
328   
329    Attempts to cancel the promise if possible. The promise being cancelled and
330    the parent most ancestor that has not yet been resolved will also be
331    cancelled. Any promises waiting on the cancelled promise to resolve will also
332    be cancelled.
333   
334  - `getState() : string`
335   
336    Returns the state of the promise. One of `pending`, `fulfilled`, or
337    `rejected`.
338   
339  - `resolve($value)`
340   
341    Fulfills the promise with the given `$value`.
342   
343  - `reject($reason)`
344   
345    Rejects the promise with the given `$reason`.
346   
347   
348  ### FulfilledPromise
349   
350  A fulfilled promise can be created to represent a promise that has been
351  fulfilled.
352   
353  ```php
354  use GuzzleHttp\Promise\FulfilledPromise;
355   
356  $promise = new FulfilledPromise('value');
357   
358  // Fulfilled callbacks are immediately invoked.
359  $promise->then(function ($value) {
360      echo $value;
361  });
362  ```
363   
364   
365  ### RejectedPromise
366   
367  A rejected promise can be created to represent a promise that has been
368  rejected.
369   
370  ```php
371  use GuzzleHttp\Promise\RejectedPromise;
372   
373  $promise = new RejectedPromise('Error');
374   
375  // Rejected callbacks are immediately invoked.
376  $promise->then(null, function ($reason) {
377      echo $reason;
378  });
379  ```
380   
381   
382  ## Promise Interoperability
383   
384  This library works with foreign promises that have a `then` method. This means
385  you can use Guzzle promises with [React promises](https://github.com/reactphp/promise)
386  for example. When a foreign promise is returned inside of a then method
387  callback, promise resolution will occur recursively.
388   
389  ```php
390  // Create a React promise
391  $deferred = new React\Promise\Deferred();
392  $reactPromise = $deferred->promise();
393   
394  // Create a Guzzle promise that is fulfilled with a React promise.
395  $guzzlePromise = new GuzzleHttp\Promise\Promise();
396  $guzzlePromise->then(function ($value) use ($reactPromise) {
397      // Do something something with the value...
398      // Return the React promise
399      return $reactPromise;
400  });
401  ```
402   
403  Please note that wait and cancel chaining is no longer possible when forwarding
404  a foreign promise. You will need to wrap a third-party promise with a Guzzle
405  promise in order to utilize wait and cancel functions with foreign promises.
406   
407   
408  ### Event Loop Integration
409   
410  In order to keep the stack size constant, Guzzle promises are resolved
411  asynchronously using a task queue. When waiting on promises synchronously, the
412  task queue will be automatically run to ensure that the blocking promise and
413  any forwarded promises are resolved. When using promises asynchronously in an
414  event loop, you will need to run the task queue on each tick of the loop. If
415  you do not run the task queue, then promises will not be resolved.
416   
417  You can run the task queue using the `run()` method of the global task queue
418  instance.
419   
420  ```php
421  // Get the global task queue
422  $queue = GuzzleHttp\Promise\Utils::queue();
423  $queue->run();
424  ```
425   
426  For example, you could use Guzzle promises with React using a periodic timer:
427   
428  ```php
429  $loop = React\EventLoop\Factory::create();
430  $loop->addPeriodicTimer(0, [$queue, 'run']);
431  ```
432   
433  *TODO*: Perhaps adding a `futureTick()` on each tick would be faster?
434   
435   
436  ## Implementation Notes
437   
438  ### Promise Resolution and Chaining is Handled Iteratively
439   
440  By shuffling pending handlers from one owner to another, promises are
441  resolved iteratively, allowing for "infinite" then chaining.
442   
443  ```php
444  <?php
445  require 'vendor/autoload.php';
446   
447  use GuzzleHttp\Promise\Promise;
448   
449  $parent = new Promise();
450  $p = $parent;
451   
452  for ($i = 0; $i < 1000; $i++) {
453      $p = $p->then(function ($v) {
454          // The stack size remains constant (a good thing)
455          echo xdebug_get_stack_depth() . ', ';
456          return $v + 1;
457      });
458  }
459   
460  $parent->resolve(0);
461  var_dump($p->wait()); // int(1000)
462   
463  ```
464   
465  When a promise is fulfilled or rejected with a non-promise value, the promise
466  then takes ownership of the handlers of each child promise and delivers values
467  down the chain without using recursion.
468   
469  When a promise is resolved with another promise, the original promise transfers
470  all of its pending handlers to the new promise. When the new promise is
471  eventually resolved, all of the pending handlers are delivered the forwarded
472  value.
473   
474  ### A Promise is the Deferred
475   
476  Some promise libraries implement promises using a deferred object to represent
477  a computation and a promise object to represent the delivery of the result of
478  the computation. This is a nice separation of computation and delivery because
479  consumers of the promise cannot modify the value that will be eventually
480  delivered.
481   
482  One side effect of being able to implement promise resolution and chaining
483  iteratively is that you need to be able for one promise to reach into the state
484  of another promise to shuffle around ownership of handlers. In order to achieve
485  this without making the handlers of a promise publicly mutable, a promise is
486  also the deferred value, allowing promises of the same parent class to reach
487  into and modify the private properties of promises of the same type. While this
488  does allow consumers of the value to modify the resolution or rejection of the
489  deferred, it is a small price to pay for keeping the stack size constant.
490   
491  ```php
492  $promise = new Promise();
493  $promise->then(function ($value) { echo $value; });
494  // The promise is the deferred value, so you can deliver a value to it.
495  $promise->resolve('foo');
496  // prints "foo"
497  ```
498   
499   
500  ## Upgrading from Function API
501   
502  A static API was first introduced in 1.4.0, in order to mitigate problems with
503  functions conflicting between global and local copies of the package. The
504  function API will be removed in 2.0.0. A migration table has been provided here
505  for your convenience:
506   
507  | Original Function | Replacement Method |
508  |----------------|----------------|
509  `queue` | `Utils::queue` |
510  `task` | `Utils::task` |
511  `promise_for` | `Create::promiseFor` |
512  `rejection_for` | `Create::rejectionFor` |
513  `exception_for` | `Create::exceptionFor` |
514  `iter_for` | `Create::iterFor` |
515  `inspect` | `Utils::inspect` |
516  `inspect_all` | `Utils::inspectAll` |
517  `unwrap` | `Utils::unwrap` |
518  `all` | `Utils::all` |
519  `some` | `Utils::some` |
520  `any` | `Utils::any` |
521  `settle` | `Utils::settle` |
522  `each` | `Each::of` |
523  `each_limit` | `Each::ofLimit` |
524  `each_limit_all` | `Each::ofLimitAll` |
525  `!is_fulfilled` | `Is::pending` |
526  `is_fulfilled` | `Is::fulfilled` |
527  `is_rejected` | `Is::rejected` |
528  `is_settled` | `Is::settled` |
529  `coroutine` | `Coroutine::of` |
530   
531   
532  ## Security
533   
534  If you discover a security vulnerability within this package, please send an email to security@tidelift.com. All security vulnerabilities will be promptly addressed. Please do not disclose security-related issues publicly until a fix has been announced. Please see [Security Policy](https://github.com/guzzle/promises/security/policy) for more information.
535   
536   
537  ## License
538   
539  Guzzle is made available under the MIT License (MIT). Please see [License File](LICENSE) for more information.
540   
541   
542  ## For Enterprise
543   
544  Available as part of the Tidelift Subscription
545   
546  The maintainers of Guzzle and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/packagist-guzzlehttp-promises?utm_source=packagist-guzzlehttp-promises&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
547