slashequip / attempt
Attempt是一个简单、流畅的类,用于尝试多次运行代码同时处理异常。
Requires
- php: ^8.0
Requires (Dev)
- pestphp/pest: ^1.21
- phpunit/phpunit: ^9.0
This package is auto-updated.
Last update: 2024-09-16 16:05:22 UTC
README
Attempt是一个简单、流畅的类,用于尝试多次运行代码同时处理异常。它在可能的情况下尝试模仿PHP内置的try/catch语法,但在此基础上增加了一些额外的魔法。
安装
Attempt已添加到packagist,可以通过composer安装
composer require slashequip/attempt
获取实例
根据您的偏好,您可以通过几种方式获取Attempt实例
use SlashEquip\Attempt\Attempt; $attempt = new Attempt(); $attempt = Attempt::make();
构建Attempt
一旦您有了实例,就可以开始构建您的Attempt。
尝试
这是唯一必需的方法,try
方法接受一个可调用参数,即您想要运行的代码。
$attempt ->try(function () { // My code that may or may not work. }) ->thenReturn();
然后返回
您可能已经注意到上面的示例中的thenReturn
方法,这个方法告诉Attempt运行。它还会返回您传递给try
方法的可调用的返回值。
还有一个then
方法,它也接受一个可调用参数,该参数将被执行,并将传递给try
可调用的返回值。
如果您喜欢,Attempt也是可调用的,这意味着在任何时候都可以调用Attempt,并且它将运行。
// $valueOne will be true $valueOne = $attempt ->try(function () { return true; }) ->thenReturn(); // $valueTwo will be false $valueTwo = $attempt ->try(function () { return true; }) ->then(function ($result) { return !$result; }); // $valueThree will be true $valueThree = $attempt ->try(function () { return true; })();
次数
您可以在遇到异常时设置Attempt应该尝试的次数见catch。
$valueOne = $attempt ->try(function () { throw new RuntimeException(); }) ->times(5) ->thenReturn(); // The above code would be run 5 times before throwing the RuntimeException
捕获
catch
方法允许您定义在尝试过程中可能遇到的异常,当将异常传递给catch
方法时,Attempt将提前抛出它遇到的任何其他类型的异常,而不是执行所有尝试。
catch
方法可以多次调用以添加多个预期的异常。
如果您没有通过catch
方法提供任何预期的异常,那么Attempt将忽略所有异常,直到所有尝试都完成。
$attempt ->try(function () { throw new UnexpectedException; }) ->catch(TheExceptionWeAreExpecting::class) ->catch(AnotherExceptionWeAreExpecting::class) ->thenReturn(); // In this example; only one attempt would be made and a UnexpectedException would be thrown
catch
方法还允许您定义一个回调,当指定的异常最终抛出时将被调用。这可以用于错误记录,或者如果您的代码需要继续,您还可以返回默认值。
$attempt ->try(function () { throw new AnExpectedException; }) ->catch(AnExpectedException::class, function (AnExpectedException $e) { error_log($e->getMessage()); return new NullBlogPost(); }) ->thenReturn();
不抛出
Attempt可以被配置为永不抛出异常,有些情况下您需要执行一些代码,但仍然继续执行您的逻辑。对于这些情况,您可以使用noThrow
。
$attempt ->try(function () { throw new RuntimeException(); }) ->noThrow() ->thenReturn(); // The above exception would not bubble up and instead, simply, be swallowed.
最终
finally
方法允许您在尝试结束时运行一个回调无论结果如何,无论尝试是否成功或抛出了异常,finally
回调始终会被运行。
$attempt ->try(function () { throw new UnexpectedException; }) ->finally(function () { // run some clean up. }) ->thenReturn(); // In this example; the finally callback would be run before the UnexpectedException is thrown
等待间隔
waitBetween
方法接受一个整数,表示尝试之间的期望毫秒数。暂停发生在代码运行之前,但不会延迟Attempt的开始。
$attempt ->try(function () use ($data) { throw new UnexpectedException; }) ->times(3) ->waitBetween(250) ->thenReturn(); // In this example, there would be a pause of 250 milliseconds between each attempt.
示例用例
use SlashEquip\Attempt\Attempt; use GuzzleHttp\Exception\ClientException; $blogPost = Attempt::make() ->try(function () use ($data) { return UnstableBlogApiServiceUsingGuzzle::post([ 'data' => $data, ]); }) ->times(3) ->waitBetween(250) ->catch(ClientException::class, function (ClientException $e) { error_log("Unstable blog api service is causing issues again.") return new BlogPost::nullableObject(); }) ->then(function ($apiResponse) { return BlogPost::fromApiResponse($apiResponse); });