wpjscc/reactphp-eventsource

即时实时更新。轻量级的 EventSource 客户端通过 HTML5 服务器端发送事件(SSE)接收实时消息。基于 ReactPHP 事件驱动架构的快速流处理。

v1.0.0 2022-04-11 12:07 UTC

This package is auto-updated.

Last update: 2024-09-07 05:34:10 UTC


README

composer require wpjscc/reactphp-eventsource -vvv dev-master
try {
    $result = React\Async\await(translate('Meet Winter CMS'));
    // promise successfully fulfilled with $result
    echo 'Result: ' . $result;
} catch (Throwable $e) {
    // promise rejected with $e
    echo 'Error: ' . $e->getMessage();
}

function translate($text) {
    $deferred = new React\Promise\Deferred();
    $es = new \Clue\React\EventSource\EventSource([
        "POST",
        'https://api.openai.com/v1/completions',
        [
            'Authorization' => 'Bearer sk-bdRUebZTlQpQndm1hhmRT3BlbkFJOqRLYJoV4u4eWY3APC',
            'Content-Type' => 'application/json',
        ],
        json_encode([
            'model' => 'text-davinci-003',
            // 'model' => 'text-davinci-002-render',
            'prompt' => "Translate into Chinese and keep the source code

            ```md
           $text
            ```",
            'temperature' => 0,
            "max_tokens" => 1500,
            "frequency_penalty" => 0,
            "presence_penalty" => 0.6,
            "stream" => true,
         ])
    ]);
    
    
    $es->on('open', function () {
        echo 'open';
    });
    $replay = '';
    $es->on('message', function (\Clue\React\EventSource\MessageEvent $message) use (&$replay) {
        $json = json_decode($message->data, true);
        if ($json) {
            $replay .= $json['choices'][0]['text'];
            echo $json['choices'][0]['text']."\n";
        } else {
            echo $message->data;
        }
    });
    
    
    $es->on('error', function ($e) use ($es, $deferred, &$replay) {
        $es->readyState = \Clue\React\EventSource\EventSource::CLOSED;
        $deferred->resolve($replay);
        echo $e->getMessage();
    });

    return $deferred->promise();
}


clue/reactphp-eventsource

CI status installs on Packagist

即时实时更新。轻量级的 EventSource 客户端通过 HTML5 服务器端发送事件(SSE)接收实时消息。基于 ReactPHP 的事件驱动架构进行快速流处理。

目录

支持我们

我们投入了大量时间开发、维护和更新我们出色的开源项目。您可以通过在 GitHub 上成为赞助商来帮助我们维持工作的高质量。赞助商将获得许多回报,有关详细信息,请参阅我们的 赞助页面

让我们一起将这些项目提升到新的水平!🚀

快速入门示例

安装后,您可以使用以下代码从任何服务器端发送事件(SSE)服务器端点流式传输消息

data: {"name":"Alice","message":"Hello everybody!"}

data: {"name":"Bob","message":"Hey Alice!"}

data: {"name":"Carol","message":"Nice to see you Alice!"}

data: {"name":"Alice","message":"What a lovely chat!"}

data: {"name":"Bob","message":"All powered by ReactPHP, such an awesome piece of technology :)"}
$es = new Clue\React\EventSource\EventSource('https://example.com/stream.php');

$es->on('message', function (Clue\React\EventSource\MessageEvent $message) {
    $json = json_decode($message->data);
    echo $json->name . ': ' . $json->message . PHP_EOL;
});

请参阅 示例

使用方法

EventSource

EventSource 类负责与远程服务器端发送事件(SSE)端点进行通信。

EventSource 对象与常见网络浏览器中的对象非常相似。除非另有说明,否则它遵循在 https://html.whatwg.com.cn/multipage/server-sent-events.html 下定义的相同语义。

其构造函数只需要远程服务器端发送事件(SSE)端点的 URL

$es = new Clue\React\EventSource\EventSource('https://example.com/stream.php');

如果您需要自定义连接器设置(DNS 解析、TLS 参数、超时、代理服务器等),您可以显式传递自定义的 ConnectorInterface 实例到 Browser 实例,并将其作为附加参数传递给 EventSource,如下所示

$connector = new React\Socket\Connector([
    'dns' => '127.0.0.1',
    'tcp' => [
        'bindto' => '192.168.10.1:0'
    ],
    'tls' => [
        'verify_peer' => false,
        'verify_peer_name' => false
    ]
]);
$browser = new React\Http\Browser($connector);

$es = new Clue\React\EventSource\EventSource('https://example.com/stream.php', $browser);

此类接受一个可选的 LoopInterface|null $loop 参数,可以用来传递用于此对象的事件循环实例。您可以使用 null 值来使用默认的事件循环。除非您确信您想显式使用给定的事件循环实例,否则不应提供此值。

消息事件

每当收到 EventSource 消息时,将发出 message 事件。

$es->on('message', function (Clue\React\EventSource\MessageEvent $message) {
    // $json = json_decode($message->data);
    var_dump($message);
});

EventSource 流在其生命周期内可能发出任意数量的消息。每个 message 事件将接收一个 MessageEvent 对象

可以使用 MessageEvent::$data 属性 来访问消息有效负载数据。它通常用于传输结构化数据,如 JSON。

data: {"name":"Alice","age":30}

data: {"name":"Bob","age":50}
$es->on('message', function (Clue\React\EventSource\MessageEvent $message) {
    $json = json_decode($message->data);
    echo "{$json->name} is {$json->age} years old" . PHP_EOL;
});

EventSource 流可能为每个传入消息指定事件类型。可以使用此 event 字段发出适当的事件类型,如下所示

data: Alice
event: join

data: Hello!
event: chat

data: Bob
event: leave
$es->on('join', function (Clue\React\EventSource\MessageEvent $message) {
    echo $message->data . ' joined' . PHP_EOL;
});

$es->on('chat', function (Clue\React\EventSource\MessageEvent $message) {
    echo 'Message: ' . $message->data . PHP_EOL;
});

$es->on('leave', function (Clue\React\EventSource\MessageEvent $message) {
    echo $message->data . ' left' . PHP_EOL;
});

请参阅MessageEvent::$type 属性以获取更多详细信息。

打开事件

当EventSource连接成功建立时,将发出open事件。

$es->on('open', function () {
    echo 'Connection opened' . PHP_EOL;
});

一旦EventSource连接打开,它可能会发出任意数量的message事件

如果无法成功打开连接,它将发出一个error事件

错误事件

当EventSource连接失败时,将发出error事件。该事件接收一个用于错误实例的单一Exception参数。

$redis->on('error', function (Exception $e) {
    echo 'Error: ' . $e->getMessage() . PHP_EOL;
});

当EventSource连接暂时断开时,将自动重试。如果服务器发送非成功的HTTP状态码或无效的Content-Type响应头,连接将永久失败。

$es->on('error', function (Exception $e) use ($es) {
    if ($es->readyState === Clue\React\EventSource\EventSource::CLOSED) {
        echo 'Permanent error: ' . $e->getMessage() . PHP_EOL;
    } else {
        echo 'Temporary error: ' . $e->getMessage() . PHP_EOL;
    }
});

请参阅EventSource::$readyState 属性

EventSource::$readyState

int $readyState属性可用于检查当前EventSource连接状态。

该状态是只读的,在其生命周期中可以是三种状态之一

  • EventSource::CONNECTING
  • EventSource::OPEN
  • EventSource::CLOSED

EventSource::$url

readonly string $url属性可用于获取构造函数中提供的EventSource URL。

close()

close(): void方法可用于强制关闭EventSource连接。

这将关闭任何活动的连接或连接尝试,并进入EventSource::CLOSED状态。

MessageEvent

MessageEvent类表示一个传入的EventSource消息。

MessageEvent::$data

readonly string $data属性可用于访问消息有效载荷数据。

data: hello
assert($message->data === 'hello');

data字段也可能跨越多行。这通常用于传输结构化数据,如JSON。

data: {
data:     "message": "hello"
data: }
$json = json_decode($message->data);
assert($json->message === 'hello');

如果消息不包含data字段或data字段为空,则消息将被丢弃而不会发出事件。

MessageEvent::$lastEventId

readonly string $lastEventId属性可用于访问最后的事件ID。

data: hello
id: 1
assert($message->data === 'hello');
assert($message->lastEventId === '1');

内部,如果连接中断,将自动使用id字段作为Last-Event-ID HTTP请求头。

如果消息不包含id字段,则$lastEventId属性将是最后一个接收的ID的值。如果没有之前的消息包含ID,它将默认为空字符串。

MessageEvent::$type

readonly string $type属性可用于访问消息事件类型。

data: Alice
event: join
assert($message->data === 'Alice');
assert($message->type === 'join');

内部,将使用event字段来发出适当的事件类型。请参阅message事件

如果消息不包含event字段或event字段为空,则$type属性将默认为message

安装

推荐通过Composer安装此库。对Composer不熟悉?新用户?

此项目遵循SemVer。这将安装最新支持的版本

$ composer require clue/reactphp-eventsource:^1

有关版本升级的详细信息,请参阅CHANGELOG

此项目旨在在所有平台上运行,因此不需要任何PHP扩展,并支持在从PHP 5.4到当前PHP 8+的旧版PHP上运行。强烈建议为此项目使用最新支持的PHP版本。

测试

要运行测试套件,您首先需要克隆此存储库,然后通过Composer安装所有依赖项(Composer)

$ composer install

要运行测试套件,请转到项目根目录并运行

$ vendor/bin/phpunit

许可证

本项目采用宽松的MIT许可协议

您知道吗?我提供定制开发服务和为版本发布和贡献提供发票的服务。如需详细信息,请联系我(@clue)。

更多

  • 如果您想了解更多关于处理数据流的信息,请参阅底层react/stream组件的文档。

  • 如果您想运行服务器端的事件源(SSE)应用程序,您可能想使用由Framework X提供的强大服务器实现。