### Implementation Notes # 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 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) --- ### Promise Api # Promise API This reference summarizes the public API provided by `guzzlehttp/promises`. Promise APIs are documented for static analysis as `PromiseInterface`. `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. ## Is `GuzzleHttp\Promise\Is` provides readable state checks: - `Is::pending(PromiseInterface $promise) : bool` - `Is::settled(PromiseInterface $promise) : bool` - `Is::fulfilled(PromiseInterface $promise) : bool` - `Is::rejected(PromiseInterface $promise) : bool` ## 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) --- ### Promise Interoperability # 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) --- ### Promise Quick Start # 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) --- ### CHANGELOG # CHANGELOG ## 3.0.1 - 2026-08-05 ### Changed - Changed the default `TReason` of `FulfilledPromise` and `Create::promiseFor()` to `never` - Changed the default `TValue` of `RejectedPromise` and `Create::rejectionFor()` to `never` ### Fixed - Fixed `EachPromise` abandoning its aggregate when the pending window drains unsettled - Fixed `EachPromise` admitting new work after its aggregate has settled ## 3.0.0 - 2026-07-20 ### Added - Added `concurrency` config support to `Utils::all()` and `Each::of()` - Added generic PHPDoc annotations to promise APIs and collection callbacks - Added recursive and `concurrency` config support to `Utils::settle()` - Allowed promises to be resolved without passing a value ### Changed - Changed `Utils::inspect()` to return actual rejection reasons - Changed `Utils::inspect()` to prefer the settled state over late wait function exceptions - Changed late rejection callbacks to follow rejected promises - Reject native PHP serialization of in-flight runtime objects - Made static helper classes non-instantiable - Require iterable inputs for promise collection helpers and `EachPromise` - Iterate `IteratorAggregate` inputs to collection helpers instead of treating them as a single value - Improved recursive `Utils::all()` handling of dynamically-added settled values and raw values ### Removed - Dropped support for PHP 7.2 and 7.3 ## 2.5.1 - 2026-07-08 ### Fixed - Fixed recursive `Utils::all()` rejecting generator inputs ## 2.5.0 - 2026-06-02 ### Deprecated - Deprecated passing non-iterable inputs to promise collection helpers and `EachPromise` ## 2.4.1 - 2026-05-20 ### Fixed - Fixed cancelling settled coroutines when no current promise remains ## 2.4.0 - 2026-05-20 ### Changed - Empty `EachPromise` instances now resolve when the task queue runs without `wait()` ## 2.3.1 - 2026-05-19 ### Fixed - Fixed `Utils::inspect()` returning the internal reason array instead of the `AggregateException` ## 2.3.0 - 2025-08-22 ### Added - PHP 8.5 support ## 2.2.0 - 2025-03-27 ### Fixed - Revert "Allow an empty EachPromise to be resolved by running the queue" ## 2.1.0 - 2025-03-27 ### Added - Allow an empty EachPromise to be resolved by running the queue ## 2.0.4 - 2024-10-17 ### Fixed - Once settled, don't allow further rejection of additional promises ## 2.0.3 - 2024-07-18 ### Changed - PHP 8.4 support ## 2.0.2 - 2023-12-03 ### Changed - Replaced `call_user_func*` with native calls ## 2.0.1 - 2023-08-03 ### Changed - PHP 8.3 support ## 2.0.0 - 2023-05-21 ### Added - Added PHP 7 type hints ### Changed - All previously non-final non-exception classes have been marked as soft-final ### Removed - Dropped PHP < 7.2 support - All functions in the `GuzzleHttp\Promise` namespace ## 1.5.3 - 2023-05-21 ### Changed - Removed remaining usage of deprecated functions ## 1.5.2 - 2022-08-07 ### Changed - Officially support PHP 8.2 ## 1.5.1 - 2021-10-22 ### Fixed - Revert "Call handler when waiting on fulfilled/rejected Promise" - Fix pool memory leak when empty array of promises provided ## 1.5.0 - 2021-10-07 ### Changed - Call handler when waiting on fulfilled/rejected Promise - Officially support PHP 8.1 ### Fixed - Fix manually settle promises generated with `Utils::task` ## 1.4.1 - 2021-02-18 ### Fixed - Fixed `each_limit` skipping promises and failing ## 1.4.0 - 2020-09-30 ### Added - Support for PHP 8 - Optional `$recursive` flag to `all` - Replaced functions by static methods ### Fixed - Fix empty `each` processing - Fix promise handling for Iterators of non-unique keys - Fixed `method_exists` crashes on PHP 8 - Memory leak on exceptions ## 1.3.1 - 2016-12-20 ### Fixed - `wait()` foreign promise compatibility ## 1.3.0 - 2016-11-18 ### Added - Adds support for custom task queues. ### Fixed - Fixed coroutine promise memory leak. ## 1.2.0 - 2016-05-18 ### Changed - Update to now catch `\Throwable` on PHP 7+ ## 1.1.0 - 2016-03-07 ### Changed - Update EachPromise to prevent recurring on a iterator when advancing, as this could trigger fatal generator errors. - Update Promise to allow recursive waiting without unwrapping exceptions. ## 1.0.3 - 2015-10-15 ### Changed - Update EachPromise to immediately resolve when the underlying promise iterator is empty. Previously, such a promise would throw an exception when its `wait` function was called. ## 1.0.2 - 2015-05-15 ### Changed - Conditionally require functions.php. ## 1.0.1 - 2015-06-24 ### Changed - Updating EachPromise to call next on the underlying promise iterator as late as possible to ensure that generators that generate new requests based on callbacks are not iterated until after callbacks are invoked. ## 1.0.0 - 2015-05-12 - Initial release --- ### README # Guzzle Promises `guzzlehttp/promises` is a small promise library used by Guzzle for asynchronous operations. It implements promise chaining, synchronous waiting, cancellation, and helpers for working with groups of promises. Most application developers use this package through [`guzzlehttp/guzzle`](https://github.com/guzzle/guzzle/blob/8.0/README.md) by calling methods such as `requestAsync()`. Install this package directly when you need promise composition without the full HTTP client. ## Installation ```bash composer require guzzlehttp/promises ``` ## Version Guidance | Version | Status | PHP Version | |---------|--------------|--------------| | 3.0 | Latest | >=7.4,<8.6 | | 2.5 | Maintenance | >=7.2.5,<8.6 | | 1.5 | End of Life | >=5.5,<8.3 | ## Quick Start ```php use GuzzleHttp\Promise\Promise; use GuzzleHttp\Promise\Utils; $promise = new Promise(); $promise->then( function ($value) { echo 'Fulfilled: ' . $value; }, function ($reason) { echo 'Rejected: ' . $reason; } ); $promise->resolve('done'); Utils::queue()->run(); ``` You can wait for a promise to complete synchronously: ```php $value = $promise->wait(); ``` When using Guzzle HTTP requests, asynchronous methods return `GuzzleHttp\Promise\PromiseInterface` instances: ```php $promise = $client->requestAsync('GET', 'https://example.com'); $response = $promise->wait(); ``` ## Documentation - [Promise Quick Start](docs/promise-quick-start.md) - [Promise API](docs/promise-api.md) - [Promise Interoperability](docs/promise-interoperability.md) - [Implementation Notes](docs/implementation-notes.md) - [Upgrade Guide](UPGRADING.md) - [Changelog](CHANGELOG.md) ## Security 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. ## License Guzzle is made available under the MIT License (MIT). Please see [License File](LICENSE) for more information. ## For Enterprise Available as part of the Tidelift Subscription 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) ---