Amphp之协程
Posted Flybeta
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Amphp之协程相关的知识,希望对你有一定的参考价值。
目录
Amphp之协程
协程是可中断的函数。在 PHP 中,它们可以使用生成器来实现。
虽然生成器通常用于使用 yield 关键字实现简单的迭代器和产生元素,但 Amp 使用 yield 作为中断点。当协程产生一个值时,协程的执行会暂时中断,允许运行其他任务,例如 I/O 处理程序、计时器或其他协程。
// 使用 Artax 获取资源并返回其主体。
$promise = Amp\\call(function () use ($http)
try
// Yield control until the generator resolves
// and return its eventual result.
$response = yield $http->request("https://example.com/");
$body = yield $response->getBody();
return $body;
catch (HttpException $e)
// If promise resolution fails the exception is
// thrown back to us and we handle it as needed.
);
每次产生一个 Promise 时,协程都会订阅该 Promise,并在 Promise 解决后自动继续它。成功解析后,协程将使用 Generator::send()
将解析值发送到生成器。如果失败,它将使用 Generator::throw()
将异常抛出到生成器中。这允许编写几乎像同步代码一样的异步代码。
请注意,无需注册回调即可使用 Promise,并且可以使用普通的 catch 子句处理错误,如果未捕获到调用上下文,它将以与同步代码中异常冒泡的相同方式冒泡。
使用
Amp\\call()
始终从您的公共 API 返回一个承诺,而不是一个\\Generator
。生成器是不应该泄露给 API 使用者的实现细节。
Yield特性(Yield Behavior)
协程中的所有 yield 必须是以下三种类型之一:
Yieldable | Description |
---|---|
Amp\\Promise | 任何 Promise 实例都可能被产生,一旦 Promise 解决,控制权将返回给协程。如果解析失败,相关异常将被抛出到生成器中,并且必须由应用程序处理,否则它将冒泡。如果解析成功,则将 promise 的解析值发送回生成器。 |
React\\Promise\\PromiseInterface | 与 Amp\\Promise 相同。任何 React Promise 都会自动适应 Amp Promise。 |
array | 产生一组 promise 使用 Amp\\Promise\\all() 隐式组合它们。元素不是 promise 的数组将导致 Amp\\InvalidYieldError。 |
Yield vs. Yield From
yield
用于“await”promise,yield from
可用于委托给子例程。
yield from
应该只用于委托给私有方法,任何公共 API 应该总是返回 Promise 而不是生成器。
当从 \\Generator 中产生一个 Promise 时,\\Generator 将暂停并在 Promise 解决后立即继续。使用 yield from
产生另一个 \\Generator。
除了使用 yield from
,你还可以使用 yield new Coroutine($this->bar());
或 yield call([$this, "bar"]);
。
示例:
class Foo
public function delegationWithCoroutine(): Amp\\Promise
return new Amp\\Coroutine($this->bar());
public function delegationWithYieldFrom(): Amp\\Promise
return Amp\\call(function ()
return yield from $this->bar();
);
public function delegationWithCallable(): Amp\\Promise
return Amp\\call([$this, 'bar']);
public function bar(): Generator
yield new Amp\\Success(1);
yield new Amp\\Success(2);
return yield new Amp\\Success(3);
Amp\\Loop::run(function ()
$foo = new Foo();
$r1 = yield $foo->delegationWithCoroutine();
$r2 = yield $foo->delegationWithYieldFrom();
$r3 = yield $foo->delegationWithCallable();
var_dump($r1);
var_dump($r2);
var_dump($r3);
);
输出:
int(3)
int(3)
int(3)
有关 yield from 的更多信息,请参阅 PHP 手册。
以上是关于Amphp之协程的主要内容,如果未能解决你的问题,请参考以下文章