I don't really understand how to catch an exception (forward it) within the onReject handler. I was wondering if anyone can point me in the right direction on how to successfully do so.
I'm sending in some async requests and when one fails with "An uncaught Exception was encountered - Type: GuzzleHttp\Exception\ClientException" it never gets caught.
I have read:
But it's not clear why the following doesn't work. My understanding is when the ClientException is thrown within the onReject (RequestException) it will then push it further down to the next onReject (ClientException) and be caught properly.
Any help would be appreciated.
$client = new GuzzleHttp\Client();
$promise = $client->requestAsync('POST', SOME_URL, [
... SOME_PARAMS ...
]);
$promise->then(
function (ResponseInterface $res) {
//ok
},
function (RequestException $e) {
//inside here throws a ClientException
}
)->then(null, function (ClientException $e) {
//Why does it not get caught/forwarded to this error handler?
});
According to the guzzle documentation,
If an exception is thrown in an $onRejected callback, subsequent $onRejected callbacks are invoked with the thrown exception as the reason.
So this should work:
$promise
->then(
function (ResponseInterface $res) {
// this will be called when the promise resolves
return $someVal;
},
function (RequestException $e) {
// this will be called when the promise resolving failed
// if you want this to bubble down further the then-line, just re-throw:
throw $e;
}
)
->then(
function ($someVal) {
},
function (RequestException $e) {
// now the above thrown Exception should be passed in here
});
Guzzle Promises follow Promises/A+ standard. Therefore we can rely on the official description to grasp the behavior you are curious about:
2.2.7.1. If either onFulfilled or onRejected returns a value
x
, run the Promise Resolution Procedure[[Resolve]](promise2, x)
.2.2.7.2. If either
onFulfilled
oronRejected
throws an exceptione
,promise2
must be rejected withe
as the reason.
And later for the 2.2.7.2 case:
2.3.2. If
x
is a promise, adopt its state
Therefore you could either follow the solution proposed by @lkoell or to return RejectedPromise
from the callback which will force a subsequent promise to adopt the rejected
state.
$promiseA = $promise
->then(
function (ResponseInterface $res) {
//ok
},
function (RequestException $e) {
//This will force $promiseB adopt $promiseC state and get rejected
return $promiseC = new RejectedPromise($clientException);
}
);
$promiseB = $promiseA->then(null, function (ClientException $e) {
// There you will get rejection
});
This way is more flexible as you can reject a promise not only with an exception but any reason (except a promise).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With