skelan / simple-promise
这是一个轻量级的Promise包实现
Requires
- php: ^7.0 || ^8.0
README
PHP的轻量级CommonJS Promises/A实现。
此文件的大部分代码来自react/promise,感谢reactphp团队提供了这样一个有用的包。
安装
确保您已安装Composer Composer。
如果没有Composer,请运行以下命令
curl -sS https://getcomposer.org/installer | php
运行安装
composer require skelan/simple-promise
概念
Deferred
Deferred 代表一个可能尚未完成的计算或工作单元。通常(但并非总是),这种计算将是在未来某个时刻异步执行并完成的。
Promise
虽然Deferred代表计算本身,但Promise代表该计算的结果。因此,每个Deferred都有一个Promise,它充当其实际结果的占位符。
API
Deferred
Deferred代表一个解决状态待定的操作。它有独立的promise和resolver部分。
$deferred = new Skelan\SimplePromise\Deferred(); $promise = $deferred->promise(); $deferred->resolve(mixed $value = null); $deferred->reject(mixed $reason = null);
Promise转发的工作原理
一些简单的例子,展示Promises/A转发的工作机制。当然,这些例子是人为构造的,在实际使用中,promise链通常跨越多个函数调用,甚至跨越您的应用架构的几个级别。
解决转发
已解决的Promise将解决值转发到下一个Promise。第一个Promise,$deferred->promise()
,将使用下面传递给$deferred->resolve()
的值进行解决。
每次调用then()
都会返回一个新的Promise,它将解决上一个处理器的返回值。这创建了一个Promise“管道”。
$deferred = new Skelan\SimplePromise\Deferred(); $deferred->promise() ->then(function ($x) { // $x will be the value passed to $deferred->resolve() below // and returns a *new promise* for $x + 1 return $x + 1; }) ->then(function ($x) { // $x === 2 // This handler receives the return value of the // previous handler. return $x + 1; }) ->then(function ($x) { // $x === 3 // This handler receives the return value of the // previous handler. return $x + 1; }) ->then(function ($x) { // $x === 4 // This handler receives the return value of the // previous handler. echo 'Resolve ' . $x; }); $deferred->resolve(1); // Prints "Resolve 4"
拒绝转发
拒绝的Promise行为类似,并且与try/catch类似:当你捕获异常时,你必须重新抛出才能使其传播。
同样,当你处理拒绝的Promise时,为了传播拒绝,可以通过返回一个拒绝的Promise或实际抛出(因为Promise将抛出的异常转换为拒绝)来“重新抛出”。
$deferred = new Skelan\SimplePromise\Deferred(); $deferred->promise() ->then(function ($x) { throw new \Exception($x + 1); }) ->otherwise(function (\Exception $x) { // Propagate the rejection throw $x; }) ->otherwise(function ($x) { echo 'Reject ' . $x->getMessage(); // 3 }); $deferred->resolve(1); // Prints "Reject 3"
最佳实践
1) try/catch演示
就像try/catch一样,你可以选择是否传播。混合解决方案和拒绝仍将以可预测的方式转发处理器结果。
try { return doSomething(); } catch(\Exception $e) { return handleError($e); } finally { doFinally(); }
$deferred = new Skelan\SimplePromise\Deferred(); $deferred->promise() ->then(function ($x) { return $x + 1; }) ->then(function ($x) { throw new \Exception($x + 1); }) ->otherwise(function (\Exception $x) { //catch exception var_dump('otherwise: ' . ($x->getMessage() + 1)); //4 }) ->always(function () { //finally var_dump('finally '); }); $deferred->resolve(1);
2) 异步调用
function remoteRequest() { $deferred = new \Skelan\SimplePromise\Deferred(function (\Skelan\SimplePromise\PromiseInterface $promise) { var_dump('call cancel.'); }); \Swoole\Timer::after(1000, function() use($deferred) { $deferred->resolve('finish: ' . time()); }); return $deferred->promise(); } remoteRequest()->then(function ($value) { var_dump('resolve: ' . time()); var_dump($value); throw new \Exception('xxx'); }, function($reason) { var_dump($reason); })->otherwise(function(\Throwable $exception) { var_dump('exception: ' . $exception->getMessage()); })->always(function($value) { var_dump('otherwise: ' . $value); });
许可
在MIT许可下发布。