ajf / hanno
为 PHP 5.5 提供的基于生成器的异步 I/O
Requires
- php: >=5.5.0
This package is not auto-updated.
Last update: 2024-09-10 02:34:13 UTC
README
Hanno 是一个用于在 PHP 中编写实时应用的异步事件循环系统。与一些类似的系统不同,它基于生成器,避免了回调的需要,大大简化了代码的读取和写入。
因为它使用生成器,所以它至少需要 PHP 5.5。
这个名字来自日语动词“反应”,反応する (Han'nō suru),指的是对反应器的使用,并致敬 ReactPHP。由于这个名字的日语发音是 Han'nō,所以实际上应该把“Hanno”读作两个分开的 'n' 声音,就像“Han'no”,但在实践中,每个人(包括我自己)都会说“Hanno” (/ˈhæ.noʊ/))。
我该如何使用它?
Hanno 是一个现代的自动加载库,支持 Composer,并通过 Packagist 提供。因此,只需要求 "ajf\Hanno"
包,就可以开始了。
Hanno 的基本结构元素是 任务。Hanno 中的任务简单地说就是普通的 Generator
,它们会在完成之前迭代。背后的思想是,当你需要等待其他事情时,使用 yield
将控制权交给其他任务,这意味着你可以高效地同时做很多事情(例如处理多个请求),而不会相互干扰,也不需要多个线程。举一个相当无聊的例子,以下生成器产生一个相当无用的任务
function counter() { for ($i = 1; $i <= 3; $i++) { yield; echo "$i\n"; } }
为了同时运行多个任务,Hanno 提供了一个 Reactor
类来处理多个任务。例如,这里我们创建一个反应器并向它添加两个计数器
use ajf\Hanno as Hanno; $reactor = new Hanno\Reactor; $reactor->addTask(counter()); $reactor->addTask(counter()); $reactor->run();
对于反应器运行的每个步骤,它将执行每个任务,运行一次迭代(即调用其 ->next()
方法),如果它没有完成(即,->valid()
返回 true),则将其调度为下次运行。请注意,您也可以将反应器作为一个任务来运行,因此实际上可以在反应器中运行反应器!例如,我们可以这样做
$reactor1 = new Hanno\Reactor; $reactor1->addTask(counter()); $reactor1->addTask(counter()); $reactor2 = new Hanno\Reactor; $reactor2->addTask(counter()); $ueber_reactor = new Hanno\Reactor; $ueber_reactor->addTask($reactor1->runAsTask()); $ueber_reactor->addTask($reactor2->runAsTask());
您可以将反应器嵌套在自身内部,但会发生 TM 糟糕的事情,所以不要尝试。 ;)
所以,现在我们已经熟悉了任务和反应器的基本知识。但如果我们想做一些真正有用的事情怎么办?反应器不会忽略 yield
产生的值。通过使用特殊的键 'until'
,您可以要求反应器挂起您的任务,直到某件事完成,并返回该任务的结果。那件事必须是一个 Awaitable
类。例如
function myTask($myAwaitable) { yield; $result = (yield 'until' => $myAwaitable); foobar($result); }
但您从哪里获取可等待的对象呢?嗯,可等待的对象通常是由执行某些操作的函数返回的。它是一个非常简单的对象,包含一个反应器将运行的任务,反应器可以“监听”以知道工作何时完成以及其结果如何,以便您的任务可以再次开始运行。您可以从一个地方获取可等待的对象,那就是 Hanno 内置的 Stream
类,它包装了 PHP 流。假设我们想找出我们的 IP 地址。我们可以像这样使用 http://ip.jsontest.com/ API
function getIPTask() { yield; $stream = new Hanno\Stream("http://ip.jsontest.com/", "r"); $data = (yield 'until' => $stream->read()); $data = json_decode($data); var_dump($data->ip); } $reactor = new Hanno\Reactor; $reactor->addTask(getIPTask()); $reactor->run();
构造函数接受现有的资源,或一个 URL 和一个模式(就像您提供给 fopen 的一样)。使用无参数的 ->read
方法将读取整个流并给我们一个最终结果为字符串的可等待对象。然后我们只需调用 json_decode
。
这就是 Hanno 的基础知识。祝您玩得开心!