How to chain multiple exception types in a promise in the ReactPhp Browser?

72 Views Asked by At

In ReactPhp, when using the Browser class, we do requests like this:

$browser
->post( $uri, $headers, $body )
->then
(
    function (Psr\Http\Message\ResponseInterface $response)
    {
        var_dump((string)$response->getBody());
    },
    function (Exception $e)
    {
        echo 'Error: ' . $e->getMessage() . PHP_EOL;
    }
);

Documented here https://github.com/reactphp/http#post

Nevertheless the Exception can be of multiple types. It can be at least of type React\Http\Message\ResponseException in the case the network connection is okey, the host is reachable, the request has been accepted and the response has been a status different from 200 OK (for example you get this ResponseException if the server returns 400 Bad Request).

In a usual try-catch block we may chain multiple exception types. If the first matches, it enters that catch block, otherwise if the next matches, it enters the second block and so on.

I'd like to to this in a cleaner way:

$browser->post( $uri, $headers, $body )
    ->then(
        function( ResponseInterface $response )
        {
            // Process my OK response
        },
        function( \Exception $exception )
        {
            $exceptionClassName = get_class( $exception );
            if( $exceptionClassName == ResponseException::class )
            {
                // Process ResponseException
            }
            else
            {
                // Process the rest of exceptions.
            }
        }
    );

Can I chain multiple "failure" handler functions in a Promise in ReactPhp in a way the PHP or the ReactPhp engine recognizes which exception type should be processed similarly to a try-catch block with multiple catches?

1

There are 1 best solutions below

1
Simon Frings On

If you're using the reactphp/http library, you'll currently need to install the reactphp/promise dependency in version 2.9.0. This project includes an ExtendedPromiseInterface with a method called otherwise(), which I believe is what you're looking for. Here's an example:

$promise
    ->otherwise(function (\RuntimeException $reason) {
        // Only catch \RuntimeException instances
        // All other types of errors will propagate automatically
    })
    ->otherwise(function ($reason) {
        // Catch other errors
    )};

Look into the reactphp/promise documentation for more details,

You can also use the reactphp/async package with its await() function to wait for the result of your $browser->post() and wrap this in a try-catch block. You can find an example for this here: https://github.com/reactphp/async#await

FYI: As we speak, we're working towards an upcoming version 3.0.0 for the promise component, which adds a new catch() method and deprecates the otherwise(). The new catch() will then be the way forward and replaces otherwise().

Hope this helps