mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2026-10-30 05:03:23 +00:00
[Web] Update composer libraries
This commit is contained in:
1297 files changed
+71585
-24460
No files matched your search
@@ -0,0 +1,72 @@
|
||||
# Implementation Notes
|
||||
|
||||
This document describes implementation details that explain observable behavior
|
||||
in `guzzlehttp/promises`, especially queue-based callback execution, iterative
|
||||
resolution, and why `Promise` also acts as the deferred value. Application code
|
||||
usually only needs the [Promise Quick Start](promise-quick-start.md) and
|
||||
[Promise API](promise-api.md).
|
||||
|
||||
## Iterative Resolution and Chaining
|
||||
|
||||
Promises are resolved iteratively by moving pending handlers between promises.
|
||||
This keeps stack size constant even for very long `then()` chains.
|
||||
|
||||
```php
|
||||
<?php
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
use GuzzleHttp\Promise\Promise;
|
||||
|
||||
$parent = new Promise();
|
||||
$p = $parent;
|
||||
|
||||
for ($i = 0; $i < 1000; $i++) {
|
||||
$p = $p->then(function ($v) {
|
||||
// The stack size remains constant.
|
||||
echo xdebug_get_stack_depth() . ', ';
|
||||
return $v + 1;
|
||||
});
|
||||
}
|
||||
|
||||
$parent->resolve(0);
|
||||
var_dump($p->wait()); // int(1000)
|
||||
|
||||
```
|
||||
|
||||
When a promise is fulfilled or rejected with a non-promise value, the promise
|
||||
takes ownership of each child promise's handlers and delivers values down the
|
||||
chain without recursion.
|
||||
|
||||
When a promise is resolved with another promise, the original promise transfers
|
||||
all of its pending handlers to the new promise. When the new promise is
|
||||
eventually resolved, all pending handlers receive the forwarded
|
||||
value.
|
||||
|
||||
## A Promise Is the Deferred
|
||||
|
||||
Some promise libraries implement promises using a deferred object to represent
|
||||
a computation and a promise object to represent the delivery of the result of
|
||||
the computation. That separation prevents consumers from modifying the value
|
||||
that will eventually be delivered.
|
||||
|
||||
Iterative resolution requires one promise to move handlers from another promise.
|
||||
To do that without making handlers publicly mutable, `Promise` is also the
|
||||
deferred value. Promises of the same class can modify each other's private
|
||||
state, including handler ownership. This means a consumer that receives a
|
||||
`Promise` can also resolve or reject it, but it keeps chaining efficient and
|
||||
stack safe.
|
||||
|
||||
```php
|
||||
$promise = new Promise();
|
||||
$promise->then(function ($value) { echo $value; });
|
||||
// The promise is the deferred value, so you can deliver a value to it.
|
||||
$promise->resolve('foo');
|
||||
GuzzleHttp\Promise\Utils::queue()->run();
|
||||
// Prints "foo"
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
- [Quick Start](promise-quick-start.md)
|
||||
- [Promise API](promise-api.md)
|
||||
- [Promise Interoperability](promise-interoperability.md)
|
||||
@@ -0,0 +1,177 @@
|
||||
# Promise API
|
||||
|
||||
This reference summarizes the public API provided by `guzzlehttp/promises`.
|
||||
Promise APIs are documented for static analysis as
|
||||
`PromiseInterface<TValue, TReason>`. `TValue` is the fulfillment value type and
|
||||
`TReason` is the rejection reason type. This typing is PHPDoc-only and does not
|
||||
change runtime behavior.
|
||||
|
||||
Callbacks registered with `then()` are queued. They are invoked when the global
|
||||
task queue runs, when a returned promise is waited on, or when the queue is
|
||||
drained by the default shutdown handler.
|
||||
|
||||
## PromiseInterface and Promise
|
||||
|
||||
`PromiseInterface` defines the common promise contract and the states
|
||||
`pending`, `fulfilled`, and `rejected`.
|
||||
|
||||
When creating a `Promise`, you can provide an optional `$waitFn` and
|
||||
`$cancelFn`. `$waitFn` receives a boolean argument and is expected to resolve or
|
||||
reject the promise. `$cancelFn` receives no arguments and is invoked when
|
||||
`cancel()` is called.
|
||||
|
||||
```php
|
||||
use GuzzleHttp\Promise\Promise;
|
||||
|
||||
$promise = new Promise(
|
||||
function (bool $recursive) use (&$promise) {
|
||||
$promise->resolve('waited');
|
||||
},
|
||||
function () {
|
||||
// Cancel the underlying operation, such as closing a socket.
|
||||
}
|
||||
);
|
||||
|
||||
assert('waited' === $promise->wait());
|
||||
```
|
||||
|
||||
A promise has the following methods:
|
||||
|
||||
- `then(?callable $onFulfilled = null, ?callable $onRejected = null) : PromiseInterface` appends fulfillment and rejection handlers and returns a new promise resolving to the return value of the called handler. If a handler is omitted, the original fulfillment value or rejection reason is forwarded.
|
||||
- `otherwise(callable $onRejected) : PromiseInterface` appends a rejection handler and returns a new promise resolving to the callback result if called, or to the original fulfillment value if the promise is fulfilled.
|
||||
- `wait(bool $unwrap = true) : mixed` synchronously waits on the promise. When `$unwrap` is `true`, fulfilled values are returned and rejected reasons are thrown. When `$unwrap` is `false`, the promise is settled without returning or throwing its result.
|
||||
- `cancel() : void` attempts to cancel the promise and dependent promises.
|
||||
- `getState() : string` returns `pending`, `fulfilled`, or `rejected`.
|
||||
- `resolve($value = null) : void` fulfills the promise with `$value`, or with `null` if no value is given.
|
||||
- `reject($reason) : void` rejects the promise with `$reason`.
|
||||
|
||||
## Settled Promises
|
||||
|
||||
`FulfilledPromise` represents an already fulfilled promise. Fulfillment
|
||||
callbacks are still queued and run when the task queue runs or the returned
|
||||
promise is waited on.
|
||||
|
||||
```php
|
||||
use GuzzleHttp\Promise\FulfilledPromise;
|
||||
use GuzzleHttp\Promise\Utils;
|
||||
|
||||
$promise = new FulfilledPromise('value');
|
||||
$promise->then(function ($value) {
|
||||
echo $value;
|
||||
});
|
||||
|
||||
Utils::queue()->run();
|
||||
```
|
||||
|
||||
`RejectedPromise` represents an already rejected promise. Rejection callbacks
|
||||
are also queued and run when the queue is drained or the returned promise is
|
||||
waited on.
|
||||
|
||||
```php
|
||||
use GuzzleHttp\Promise\RejectedPromise;
|
||||
use GuzzleHttp\Promise\Utils;
|
||||
|
||||
$promise = new RejectedPromise('Error');
|
||||
$promise->then(null, function ($reason) {
|
||||
echo $reason;
|
||||
});
|
||||
|
||||
Utils::queue()->run();
|
||||
```
|
||||
|
||||
## Utils
|
||||
|
||||
`GuzzleHttp\Promise\Utils` provides helpers for inspecting, aggregating, and
|
||||
queuing promise work.
|
||||
|
||||
- `Utils::queue(?TaskQueueInterface $assign = null) : TaskQueueInterface` returns the global task queue, or assigns a replacement queue when `$assign` is provided.
|
||||
- `Utils::task(callable $task) : PromiseInterface` adds a task to the global queue and returns a promise that is fulfilled or rejected with the task result.
|
||||
- `Utils::inspect(PromiseInterface $promise) : array` waits for one promise to settle and returns an inspection array with `state` and either `value` or `reason`.
|
||||
- `Utils::inspectAll(iterable $promises) : array` inspects each promise and returns inspection arrays keyed like the input iterable.
|
||||
- `Utils::unwrap(iterable $promises) : array` waits on all promises and returns fulfilled values, throwing if any promise rejects.
|
||||
- `Utils::all(iterable $promises, bool $recursive = false, array $config = []) : PromiseInterface` returns a promise fulfilled with all values, or rejected when any input rejects.
|
||||
- `Utils::settle(iterable $promises, bool $recursive = false, array $config = []) : PromiseInterface` returns a promise fulfilled with inspection arrays after all inputs settle.
|
||||
- `Utils::some(int $count, iterable $promises) : PromiseInterface` fulfills with the values of the first `$count` promises to fulfill, in the order they appear in the input, or rejects with `AggregateException` if too few fulfill.
|
||||
- `Utils::any(iterable $promises) : PromiseInterface` fulfills with the first fulfilled value, or rejects with `AggregateException` if none fulfill.
|
||||
|
||||
`Utils::all()` and `Utils::settle()` accept `['concurrency' => 5]` or
|
||||
`['concurrency' => callable]` for lazy iterables. This limits how many items are
|
||||
pulled from the iterable at one time; it does not throttle promises that have
|
||||
already been created or started.
|
||||
|
||||
```php
|
||||
use GuzzleHttp\Promise\Utils;
|
||||
|
||||
$promise = Utils::all($promises, false, ['concurrency' => 5]);
|
||||
```
|
||||
|
||||
## Create
|
||||
|
||||
`GuzzleHttp\Promise\Create` provides factories used by the promise
|
||||
implementation and by callers that need to normalize values.
|
||||
|
||||
- `Create::promiseFor($value) : PromiseInterface` returns `$value` when it is already a Guzzle promise, wraps foreign thenables in a Guzzle promise, or returns a fulfilled promise for plain values.
|
||||
- `Create::rejectionFor($reason) : PromiseInterface` returns `$reason` when it is already a promise, or returns a rejected promise for plain reasons.
|
||||
- `Create::exceptionFor($reason) : Throwable` returns throwable reasons as-is, or wraps non-throwable reasons in `RejectionException`.
|
||||
- `Create::iterFor(iterable $value) : Iterator` returns an iterator for arrays, iterators, iterator aggregates, and traversables.
|
||||
|
||||
## State
|
||||
|
||||
`GuzzleHttp\Promise\State` provides readable state checks:
|
||||
|
||||
- `State::isPending(PromiseInterface $promise) : bool`
|
||||
- `State::isSettled(PromiseInterface $promise) : bool`
|
||||
- `State::isFulfilled(PromiseInterface $promise) : bool`
|
||||
- `State::isRejected(PromiseInterface $promise) : bool`
|
||||
|
||||
`GuzzleHttp\Promise\Is` is deprecated because PHP 8.6 deprecates `is` as a class
|
||||
name, and will be removed in Guzzle Promises 4.0. Replace `Is::pending()`,
|
||||
`Is::settled()`, `Is::fulfilled()`, and `Is::rejected()` with the matching
|
||||
`State` methods.
|
||||
|
||||
## Each and EachPromise
|
||||
|
||||
`Each::of()` consumes an iterable of promises or values and invokes callbacks as
|
||||
items settle. Fulfillment callbacks receive the fulfilled value, iterable key,
|
||||
and aggregate promise. Rejection callbacks receive the rejection reason,
|
||||
iterable key, and aggregate promise. Callback return values are ignored.
|
||||
|
||||
```php
|
||||
use GuzzleHttp\Promise\Each;
|
||||
|
||||
$promise = Each::of($promises, $onFulfilled, $onRejected, ['concurrency' => 5]);
|
||||
```
|
||||
|
||||
- `Each::of(iterable $iterable, ?callable $onFulfilled = null, ?callable $onRejected = null, array $config = []) : PromiseInterface` consumes the iterable and optionally limits lazy iteration with `concurrency`.
|
||||
- `Each::ofLimit(iterable $iterable, $concurrency, ?callable $onFulfilled = null, ?callable $onRejected = null) : PromiseInterface` is a convenience wrapper for `Each::of()` with a concurrency limit.
|
||||
- `Each::ofLimitAll(iterable $iterable, $concurrency, ?callable $onFulfilled = null) : PromiseInterface` is like `ofLimit()`, but rejects the aggregate promise on the first rejection.
|
||||
- `EachPromise` is the configurable class behind `Each`; use it directly when you need `fulfilled`, `rejected`, and `concurrency` keys in one configuration array.
|
||||
|
||||
The concurrency options limit lazy promise creation. For HTTP request
|
||||
concurrency, use `GuzzleHttp\Pool` from `guzzlehttp/guzzle`.
|
||||
|
||||
## Coroutine
|
||||
|
||||
`Coroutine::of(callable $generatorFn) : Coroutine` creates a promise resolved by
|
||||
a generator that yields values or promises. The generator resumes with each
|
||||
fulfilled value, and rejections are thrown into the generator.
|
||||
|
||||
## Task Queue
|
||||
|
||||
`TaskQueueInterface` exposes `isEmpty()`, `add(callable $task)`, and `run()`.
|
||||
`TaskQueue` executes queued tasks in FIFO order. The default queue runs at
|
||||
process shutdown unless disabled, and `wait()` drains the queue while resolving
|
||||
the promise being waited on.
|
||||
|
||||
## Exceptions
|
||||
|
||||
- `RejectionException` is thrown by `wait()` when a rejected promise has a non-throwable reason. The original reason is available through `getReason()`.
|
||||
- `AggregateException` extends `RejectionException` and is used by `Utils::some()` and `Utils::any()` when too few promises fulfill.
|
||||
- `CancellationException` extends `RejectionException` and is used as the rejection reason for cancelled promises.
|
||||
|
||||
## Related
|
||||
|
||||
- [Quick Start](promise-quick-start.md)
|
||||
- [Promise Interoperability](promise-interoperability.md)
|
||||
- [Implementation Notes](implementation-notes.md)
|
||||
- [Upgrade Guide](../UPGRADING.md)
|
||||
@@ -0,0 +1,78 @@
|
||||
# Promise Interoperability
|
||||
|
||||
This guide explains how Guzzle promises interact with foreign promise
|
||||
implementations. A foreign promise is any object with a `then` method, such as a
|
||||
[React promise](https://github.com/reactphp/promise). When a foreign promise is
|
||||
returned from a `then` callback, Guzzle forwards resolution to that promise.
|
||||
|
||||
## Foreign Promises
|
||||
|
||||
Capture the promise returned from `then()`. That chained promise is the Guzzle
|
||||
promise that follows the foreign promise's eventual result.
|
||||
|
||||
```php
|
||||
use GuzzleHttp\Promise\Promise;
|
||||
use GuzzleHttp\Promise\Utils;
|
||||
|
||||
$deferred = new React\Promise\Deferred();
|
||||
$reactPromise = $deferred->promise();
|
||||
|
||||
$guzzlePromise = new Promise();
|
||||
$chained = $guzzlePromise->then(function ($value) use ($reactPromise) {
|
||||
// Use the Guzzle value, then continue with the React promise.
|
||||
return $reactPromise;
|
||||
});
|
||||
|
||||
$chained->then(function ($value) {
|
||||
echo $value;
|
||||
});
|
||||
|
||||
$guzzlePromise->resolve('start');
|
||||
Utils::queue()->run();
|
||||
|
||||
$deferred->resolve('done');
|
||||
Utils::queue()->run();
|
||||
```
|
||||
|
||||
Forwarding a foreign promise does not make Guzzle able to synchronously wait on
|
||||
or cancel the foreign operation. The chained Guzzle promise settles only after
|
||||
the foreign implementation invokes the callbacks registered through `then()`.
|
||||
If the foreign promise has no compatible `wait()` or `cancel()` behavior, Guzzle
|
||||
cannot invent that behavior.
|
||||
|
||||
Use `Create::promiseFor($foreignPromise)` to shadow a foreign thenable as a
|
||||
Guzzle promise. If the foreign object exposes `wait()` or `cancel()` methods,
|
||||
the wrapper uses them. Otherwise, use the foreign implementation's event loop or
|
||||
completion mechanism and drain Guzzle's task queue when callbacks need to run.
|
||||
|
||||
## Event Loop Integration
|
||||
|
||||
Guzzle promises use a task queue to keep stack size constant and to run promise
|
||||
callbacks asynchronously. When waiting on promises synchronously, the task queue
|
||||
is automatically run while resolving the blocking promise and forwarded Guzzle
|
||||
promises.
|
||||
|
||||
When using promises asynchronously in an event loop, run the task queue on loop
|
||||
ticks. If you do not run the task queue, Guzzle promise callbacks may remain
|
||||
queued.
|
||||
|
||||
```php
|
||||
$queue = GuzzleHttp\Promise\Utils::queue();
|
||||
$queue->run();
|
||||
```
|
||||
|
||||
For example, you could use Guzzle promises with React using a short periodic
|
||||
timer. Avoid zero-interval timers because they may keep the loop busy even when
|
||||
there is no promise work to run.
|
||||
|
||||
```php
|
||||
$queue = GuzzleHttp\Promise\Utils::queue();
|
||||
$loop = React\EventLoop\Factory::create();
|
||||
$loop->addPeriodicTimer(0.01, [$queue, 'run']);
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
- [Quick Start](promise-quick-start.md)
|
||||
- [Promise API](promise-api.md)
|
||||
- [Implementation Notes](implementation-notes.md)
|
||||
@@ -0,0 +1,319 @@
|
||||
# Promise Quick Start
|
||||
|
||||
This guide covers the common promise operations needed when using
|
||||
`guzzlehttp/promises` directly: registering callbacks, resolving or rejecting
|
||||
promises, waiting synchronously, composing chains, and using generator-based
|
||||
flows. For the full public surface, see the [Promise API](promise-api.md).
|
||||
|
||||
A *promise* represents the eventual result of an asynchronous operation. The
|
||||
primary way of interacting with a promise is through its `then` method, which
|
||||
registers callbacks to receive either the eventual value or the reason why the
|
||||
promise cannot be fulfilled.
|
||||
|
||||
Guzzle promise callbacks are queued. They run when the task queue is drained,
|
||||
for example by `Utils::queue()->run()`, by waiting on a returned promise, or by
|
||||
the default shutdown handler at the end of the PHP process. Examples that show
|
||||
callback output drain the queue explicitly.
|
||||
|
||||
## Callbacks
|
||||
|
||||
Callbacks are registered with the `then` method by providing an optional
|
||||
`$onFulfilled` followed by an optional `$onRejected` function.
|
||||
|
||||
```php
|
||||
use GuzzleHttp\Promise\Promise;
|
||||
|
||||
$promise = new Promise();
|
||||
$promise->then(
|
||||
// $onFulfilled
|
||||
function ($value) {
|
||||
echo 'The promise was fulfilled.';
|
||||
},
|
||||
// $onRejected
|
||||
function ($reason) {
|
||||
echo 'The promise was rejected.';
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
*Resolving* a promise means that you either fulfill a promise with a *value* or
|
||||
reject a promise with a *reason*. Callbacks registered with `then` are invoked
|
||||
only once and in the order in which they were added when the queue is drained.
|
||||
|
||||
## Resolving a Promise
|
||||
|
||||
Promises are fulfilled using the `resolve($value = null)` method. Calling
|
||||
`resolve()` without an argument fulfills the promise with `null`. Resolving a
|
||||
promise with any value other than a `GuzzleHttp\Promise\RejectedPromise` queues
|
||||
the `$onFulfilled` callbacks. Resolving with a rejected promise rejects the
|
||||
promise and queues the `$onRejected` callbacks.
|
||||
|
||||
```php
|
||||
use GuzzleHttp\Promise\Promise;
|
||||
use GuzzleHttp\Promise\Utils;
|
||||
|
||||
$promise = new Promise();
|
||||
$promise
|
||||
->then(function ($value) {
|
||||
return 'Hello, ' . $value;
|
||||
})
|
||||
->then(function ($value) {
|
||||
echo $value;
|
||||
});
|
||||
|
||||
$promise->resolve('reader.');
|
||||
Utils::queue()->run();
|
||||
// Outputs "Hello, reader."
|
||||
```
|
||||
|
||||
## Promise Forwarding
|
||||
|
||||
Promises can be chained one after the other. Each `then` call returns a new
|
||||
promise. The return value of a callback is forwarded to the next promise in the
|
||||
chain. Returning a promise from a callback makes the next promise wait for that
|
||||
returned promise to settle.
|
||||
|
||||
```php
|
||||
use GuzzleHttp\Promise\Promise;
|
||||
use GuzzleHttp\Promise\Utils;
|
||||
|
||||
$promise = new Promise();
|
||||
$nextPromise = new Promise();
|
||||
|
||||
$promise
|
||||
->then(function ($value) use ($nextPromise) {
|
||||
echo $value;
|
||||
|
||||
return $nextPromise;
|
||||
})
|
||||
->then(function ($value) {
|
||||
echo $value;
|
||||
});
|
||||
|
||||
$promise->resolve('A');
|
||||
Utils::queue()->run();
|
||||
// Outputs "A"
|
||||
|
||||
$nextPromise->resolve('B');
|
||||
Utils::queue()->run();
|
||||
// Outputs "B"
|
||||
```
|
||||
|
||||
## Promise Rejection
|
||||
|
||||
When a promise is rejected, the `$onRejected` callbacks are invoked with the
|
||||
rejection reason when the queue is drained.
|
||||
|
||||
```php
|
||||
use GuzzleHttp\Promise\Promise;
|
||||
use GuzzleHttp\Promise\Utils;
|
||||
|
||||
$promise = new Promise();
|
||||
$promise->then(null, function ($reason) {
|
||||
echo $reason;
|
||||
});
|
||||
|
||||
$promise->reject('Error!');
|
||||
Utils::queue()->run();
|
||||
// Outputs "Error!"
|
||||
```
|
||||
|
||||
## Rejection Forwarding
|
||||
|
||||
If an exception is thrown in an `$onRejected` callback, subsequent
|
||||
`$onRejected` callbacks receive the thrown exception as the reason.
|
||||
|
||||
```php
|
||||
use GuzzleHttp\Promise\Promise;
|
||||
use GuzzleHttp\Promise\Utils;
|
||||
|
||||
$promise = new Promise();
|
||||
$promise->then(null, function ($reason) {
|
||||
throw new Exception($reason);
|
||||
})->then(null, function ($reason) {
|
||||
assert($reason->getMessage() === 'Error!');
|
||||
});
|
||||
|
||||
$promise->reject('Error!');
|
||||
Utils::queue()->run();
|
||||
```
|
||||
|
||||
You can also forward a rejection down the promise chain by returning a
|
||||
`GuzzleHttp\Promise\RejectedPromise` in either an `$onFulfilled` or
|
||||
`$onRejected` callback.
|
||||
|
||||
```php
|
||||
use GuzzleHttp\Promise\Promise;
|
||||
use GuzzleHttp\Promise\RejectedPromise;
|
||||
use GuzzleHttp\Promise\Utils;
|
||||
|
||||
$promise = new Promise();
|
||||
$promise->then(null, function ($reason) {
|
||||
return new RejectedPromise($reason);
|
||||
})->then(null, function ($reason) {
|
||||
assert($reason === 'Error!');
|
||||
});
|
||||
|
||||
$promise->reject('Error!');
|
||||
Utils::queue()->run();
|
||||
```
|
||||
|
||||
If an exception is not thrown in an `$onRejected` callback and the callback
|
||||
does not return a rejected promise, downstream `$onFulfilled` callbacks are
|
||||
invoked using the value returned from the `$onRejected` callback.
|
||||
|
||||
```php
|
||||
use GuzzleHttp\Promise\Promise;
|
||||
use GuzzleHttp\Promise\Utils;
|
||||
|
||||
$promise = new Promise();
|
||||
$promise
|
||||
->then(null, function ($reason) {
|
||||
return "It's ok";
|
||||
})
|
||||
->then(function ($value) {
|
||||
assert($value === "It's ok");
|
||||
});
|
||||
|
||||
$promise->reject('Error!');
|
||||
Utils::queue()->run();
|
||||
```
|
||||
|
||||
## Synchronous Wait
|
||||
|
||||
You can synchronously force promises to complete using a promise's `wait`
|
||||
method. When creating a promise, you can provide a wait function that is used
|
||||
to synchronously complete the promise. The wait function receives a boolean
|
||||
argument and is expected to resolve or reject the promise. If the wait function
|
||||
does not settle the promise, an exception is thrown.
|
||||
|
||||
```php
|
||||
use GuzzleHttp\Promise\Promise;
|
||||
|
||||
$promise = new Promise(function (bool $recursive) use (&$promise) {
|
||||
$promise->resolve('foo');
|
||||
});
|
||||
|
||||
echo $promise->wait();
|
||||
// Outputs "foo"
|
||||
```
|
||||
|
||||
If a throwable is encountered while invoking the wait function of a promise,
|
||||
the promise is rejected with the throwable and the throwable is thrown.
|
||||
|
||||
```php
|
||||
$promise = new Promise(function (bool $recursive) use (&$promise) {
|
||||
throw new Exception('foo');
|
||||
});
|
||||
|
||||
$promise->wait(); // Throws the exception.
|
||||
```
|
||||
|
||||
Calling `wait` on a promise that has been fulfilled will not trigger the wait
|
||||
function. It will simply return the previously resolved value.
|
||||
|
||||
```php
|
||||
$promise = new Promise(function (bool $recursive) { die('this is not called!'); });
|
||||
$promise->resolve('foo');
|
||||
|
||||
echo $promise->wait();
|
||||
// Outputs "foo"
|
||||
```
|
||||
|
||||
Calling `wait` on a promise that has been rejected will throw. If the rejection
|
||||
reason is an instance of `\Throwable`, the reason is thrown. Otherwise, a
|
||||
`GuzzleHttp\Promise\RejectionException` is thrown and the reason can be
|
||||
obtained by calling `getReason()` on the exception.
|
||||
|
||||
```php
|
||||
$promise = new Promise();
|
||||
$promise->reject('foo');
|
||||
$promise->wait();
|
||||
```
|
||||
|
||||
> PHP Fatal error: Uncaught exception 'GuzzleHttp\Promise\RejectionException' with message 'The promise was rejected with reason: foo'
|
||||
|
||||
## Unwrapping a Promise
|
||||
|
||||
When synchronously waiting on a promise, you are joining the state of the
|
||||
promise into the current execution: the fulfilled value is returned, or the
|
||||
rejection reason is thrown. This is called "unwrapping" the promise. Waiting on
|
||||
a promise unwraps by default.
|
||||
|
||||
You can force a promise to resolve and *not* unwrap its state by passing
|
||||
`false` to `wait()`:
|
||||
|
||||
```php
|
||||
$promise = new Promise();
|
||||
$promise->reject('foo');
|
||||
|
||||
// This does not throw. It only ensures the promise has been resolved.
|
||||
$promise->wait(false);
|
||||
```
|
||||
|
||||
When unwrapping a promise, the resolved value of the promise will be waited on
|
||||
until the unwrapped value is not a promise. This means that if promise A is
|
||||
resolved with promise B, unwrapping promise A returns the value delivered to
|
||||
promise B.
|
||||
|
||||
When you do not unwrap the promise, no value is returned.
|
||||
|
||||
## Inspecting a Promise
|
||||
|
||||
`Utils::inspect($promise)` waits for a promise to settle and returns an array
|
||||
describing its final state. For rejected promises, the `reason` entry is the
|
||||
actual rejection reason delivered to rejection callbacks.
|
||||
|
||||
This means `RejectionException` and subclasses are not unwrapped by
|
||||
`inspect()`. For example, cancelled promises inspect with a
|
||||
`CancellationException` reason.
|
||||
|
||||
## Generator-Based Async
|
||||
|
||||
`Coroutine::of()` creates a promise from a generator that yields values or
|
||||
promises. The generator resumes each time the yielded value settles, which can
|
||||
make sequential asynchronous flows easier to read.
|
||||
|
||||
```php
|
||||
use GuzzleHttp\Promise\Coroutine;
|
||||
use GuzzleHttp\Promise\FulfilledPromise;
|
||||
|
||||
$promise = Coroutine::of(function () {
|
||||
$first = yield new FulfilledPromise('A');
|
||||
$second = yield new FulfilledPromise($first . 'B');
|
||||
|
||||
yield $second . 'C';
|
||||
});
|
||||
|
||||
echo $promise->wait();
|
||||
// Outputs "ABC"
|
||||
```
|
||||
|
||||
If a yielded promise rejects, the rejection is thrown into the generator. Catch
|
||||
it inside the generator to recover, or let it reject the coroutine promise.
|
||||
|
||||
## Cancellation
|
||||
|
||||
You can cancel a promise that has not yet been fulfilled using `cancel()`. When
|
||||
creating a promise, you can provide an optional cancel function that cancels the
|
||||
underlying operation, such as closing a socket or aborting a query.
|
||||
|
||||
```php
|
||||
use GuzzleHttp\Promise\Promise;
|
||||
|
||||
$promise = new Promise(null, function () {
|
||||
// Cancel the underlying operation.
|
||||
});
|
||||
|
||||
$promise->cancel();
|
||||
```
|
||||
|
||||
Cancellation rejects the promise with a `CancellationException` unless the
|
||||
cancel function settles the promise first.
|
||||
|
||||
## Related
|
||||
|
||||
- [Promise API](promise-api.md)
|
||||
- [Promise Interoperability](promise-interoperability.md)
|
||||
- [Implementation Notes](implementation-notes.md)
|
||||
- [Upgrade Guide](../UPGRADING.md)
|
||||
Reference in new issue
Block a user