ReactPHP Promise

repository·3.x·Indexed 25 days ago

https://github.com/reactphp/promise

A lightweight CommonJS Promises/A implementation for PHP designed for asynchronous programming. It provides tools for managing asynchronous operations via Deferred and Promise objects, supporting promise chaining with then(), error handling with catch(), and cleanup with finally(). Includes utility functions like all(), race(), and any() for managing collections of promises, and supports PHP 7.1 through PHP 8+.

Tokens
1.9K
Snippets
7
Records
11
Agent score
32%

What's inside reactphp-promise

  1. How Deferred and Promise work together

    3.x

    In this library, a Deferred represents a computation or unit of work that may not have completed yet (the process), while a Promise represents the eventual result of that computation (the placeholder).

    Typically, you create a Deferred object to manage an asynchronous operation. You then use $deferred->promise() to obtain a Promise that you can return to consumers. The Deferred object retains the authority to resolve or reject that promise.

  2. Install React Promise via Composer

    3.x

    Install the latest supported version of the library using Composer:

    composer require react/promise:^3.2

    This project supports PHP 7.1 through PHP 8+. If you need to support older PHP versions, you can target multiple major versions simultaneously:

    composer require "react/promise:^3 || ^2 || ^1"
  3. Transform promises with PromiseInterface::then()

    3.x

    The then() method registers fulfillment and rejection handlers. It returns a new promise that implements the transformation, allowing for promise chaining (pipelines).

    • $onFulfilled (optional): Called with the fulfillment value. If it returns a value, the new promise fulfills with that value. If it returns a promise, the new promise follows that promise.
    • $onRejected (optional): Called with the rejection reason. If it throws or returns a rejected promise, the new promise rejects.

    Guarantees:

    1. Only one of $onFulfilled or $onRejected will be called.
    2. Handlers will never be called more than once.
    $transformedPromise = $promise->then(callable $onFulfilled = null, callable $onRejected = null);
  4. Join multiple promises with React\Promise functions

    3.x

    The library provides several static functions to manage collections of promises:

    • resolve(mixed $promiseOrValue): Creates a promise for a value or a thenable.
    • reject(\Throwable $reason): Creates a rejected promise.
    • all(iterable $promisesOrValues): Returns a promise that resolves only when all items in the collection have resolved. The resolution value is an array of all results.
    • race(iterable $promisesOrValues): Returns a promise that settles as soon as the first promise in the collection settles (either fulfills or rejects).
    • any(iterable $promisesOrValues): Returns a promise that resolves when any one item resolves. It only rejects if all items are rejected (returning a CompositeException).

    Note: All these collection functions support cancellation; cancelling the returned promise will cancel all promises in the collection.

  5. Configure the global rejection handler

    3.x

    Use React\Promise\set_rejection_handler() to define a global callback for unhandled promise rejections. This is useful for custom logging or error reporting.

    • The callback must accept a single \Throwable argument (or null to restore the default handler).
    • The callback must not throw an exception, or the program will terminate with a fatal error.
    • It returns the previous handler or null if the default was used.
  6. Use Deferred to manage asynchronous operations

    3.x

    Use the React\Promise\Deferred class when you need to manually control the resolution or rejection of a promise, such as when wrapping a callback-based API.

    • $deferred->promise(): Returns the promise associated with the deferred.
    • $deferred->resolve(mixed $value): Resolves the promise with the provided value. If $value is itself a promise, the deferred's promise will transition to the state of that promise.
    • $deferred->reject(\Throwable $reason): Rejects the promise with the provided error/reason.
    function getAwesomeResultPromise()
    {
        $deferred = new React\Promise\Deferred();
    
        // Example: wrapping a callback-style function
        computeAwesomeResultAsynchronously(function (\Throwable $error, $result) use ($deferred) {
            if ($error) {
                $deferred->reject($error);
            } else {
                $deferred->resolve($result);
            }
        });
    
        return $deferred->promise();
    }
  7. Create a promise with the Promise constructor

    3.x

    Use the React\Promise\Promise constructor to create a promise where the state is controlled by a resolver function.

    • $resolver: A function called immediately. It receives $resolve and $reject callbacks.
    • $canceller (optional): A function called when $promise->cancel() is invoked. It is used to abort ongoing operations (like network requests).

    If the resolver or canceller throws an exception, the promise is automatically rejected with that exception.

    $resolver = function (callable $resolve, callable $reject) {
        $resolve($awesomeResult);
        // or $reject($nastyError);
    };
    
    $canceller = function () {
        throw new Exception('Promise cancelled');
    };
    
    $promise = new React\Promise\Promise($resolver, $canceller);
  8. Execute cleanup tasks with PromiseInterface::finally()

    3.x

    The finally() method allows you to execute code when a promise is either fulfilled or rejected, regardless of the outcome. It is used for cleanup tasks (similar to a synchronous finally block).

    • The callback passed to finally() receives no arguments.
    • If the original promise fulfills and the finally callback succeeds, the new promise fulfills with the original value.
    • If the original promise rejects and the finally callback succeeds, the new promise rejects with the original reason.
    • If the finally callback throws or returns a rejected promise, the new promise will reject with that new error/reason.
    $newPromise = $promise->finally(callable $onFulfilledOrRejected);
  9. Handle errors with PromiseInterface::catch()

    3.x

    The catch() method is a shortcut for $promise->then(null, $onRejected). It allows you to handle rejections in a promise chain.

    You can type-hint the $reason argument in your callback to catch only specific types of errors. Other errors will automatically propagate down the chain.

    $promise
        ->catch(function (\RuntimeException $reason) {
            // Only catch \RuntimeException instances
        })
        ->catch(function (\Throwable $reason) {
            // Catch all other errors
        });
  10. Cancel a promise with PromiseInterface::cancel()

    3.x

    The cancel() method notifies the creator of the promise that the result is no longer needed.

    Note: Calling cancel() has no effect if the promise has already been settled (fulfilled or rejected).

    $promise->cancel();
  11. Handle multiple errors with CompositeException

    3.x

    When using promise combinators like some() or any(), a promise may be rejected with multiple errors if the conditions for success are not met (e.g., too many input promises reject). In these cases, the library throws a React\Promise\Exception\CompositeException.

    You can retrieve the collection of individual errors by calling the getThrowables() method on the caught exception.