为何Guzzle Promise的then方法中onRejected函数仍会抛出异常?
解决Guzzle Promise wait()重复记录日志的问题
你遇到的问题核心是Guzzle Promise的wait(true)(默认参数为true)会在Promise被rejected时主动抛出异常,哪怕你已经通过then的第二个回调(onRejected)处理了异常。这就导致onRejected里记录一次日志,wait的try-catch又记录一次,造成重复。
原因解析
wait($unwrap = true)的$unwrap参数决定了是否将rejected状态的Promise转换为异常抛出:
- 当
$unwrap = true(默认):如果Promise被rejected,wait会直接抛出对应的异常 - 当
$unwrap = false:wait只会返回rejected的原因,不会抛出异常
解决方案
方案1:调用wait(false)避免抛出异常
直接将wait的参数设为false,这样异常只会在onRejected回调中处理一次:
$promise = $this->client->sendAsync($request); $promise->then( function ($response) use (...) { // 处理成功逻辑 }, function ($exception) { $this->logger->error("Failed " . $exception->getMessage()); } ); // 禁用unwrap,不抛出异常 $promise->wait(false);
方案2:使用catch()方法统一处理异常(更推荐)
用catch()方法替代then的第二个回调,它会返回一个新的Promise,当原Promise被rejected时,catch的回调会执行,并且新Promise会转为resolved状态(除非catch内部再次抛出异常),此时调用wait就不会再抛出异常:
$promise = $this->client->sendAsync($request); $promise->then( function ($response) use (...) { // 处理成功逻辑 } )->catch(function ($exception) { $this->logger->error("Failed " . $exception->getMessage()); })->wait(); // 这里无需try-catch,catch已处理rejection
为什么之前链式then没用?
链式调用的第二个then如果没有专门处理rejection,原Promise的rejected状态会一直向下传递,最终wait(true)还是会抛出异常。而catch()是专门用来捕获并终止rejection传递的方法,能彻底避免wait再次抛出异常。
内容的提问来源于stack exchange,提问作者user23674741
相关产品推荐
相关产品推荐

