iphper/event-source

1.0.0 2024-04-24 10:18 UTC

This package is auto-updated.

Last update: 2025-05-24 12:45:56 UTC


README

event-source 是简单的PHP服务端对于SSE(Server-Sent Events)的封装

##安装

composer require iphper/event-source

使用示例

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>event-srouce-example</title>
</head>
<body>
    <button id="beginBtn">开始获取</button>
    <ul id="list"></ul>
</body>
</html>

js

let listDom = document.getElementById('list');
document.getElementById('beginBtn').addEventListener('click', () => {
    console.log("开始监听")
    const eventSource = new EventSource("example.php");
    // 1、默认形式监听message事件
    // eventSource.onmessage = function(event){
    //     console.log('onmessage', event)
    //     let item = document.createElement("li")
    //     let data = JSON.parse(event.data);
    //     item.innerHTML = data.message
    //     listDom.appendChild(item)
    // }

    // 2、自定义形式监听message事件
    eventSource.addEventListener('message', function(event) {
        console.log('onmessage', event)
        let item = document.createElement("li")
        let data = JSON.parse(event.data);
        item.innerHTML = data.message
        listDom.appendChild(item)
    });

    // 监听stop事件
    eventSource.addEventListener('stop', function(event) {
        console.log('服务端传来:', event.data)
        eventSource.close();
    });

    // 监听error事件
    eventSource.onerror = function(errs) {
        console.log('出错了')
        console.error(errs)
    }

    // ... 监听其它事件
});

php-fpm

use EventSource\EventSource;

$eventSource = new EventSource(3, '新消息123456789');
while(true) {
    // $eventSource->write(); // write与json方法仅对非string类型数据进行json格式化
    // 不传参数时,会直接发送构造方法中的'新消息123456789'; 若构造方法也没传则发送空串
    $eventSource->json([
        'message' => '消息'.random_int(1, 1000),
        'time' => time()
    ]);
    // 判断是否关闭连接
    if ($eventSource->reborted()) {
        break;
    }
    sleep(1);
}

swoole

use EventSource\SwooleEventSource;
use Swoole\Http\Request;
use Swoole\Http\Response;
use Swoole\Http\Server;
use Swoole\Coroutine;


$http = new Server('0.0.0.0', 18088);
$http->on('request', function (Request $request, Response $response) {

    if ($request->server['path_info'] == '/favicon.ico' || $request->server['request_uri'] == '/favicon.ico') {
        $response->end();
        return;
    }
    echo 'path:', $request->server['request_uri'],PHP_EOL;

    if ($request->server['path_info'] == '/index.html') {
        $response->write(file_get_contents(__DIR__.'/index.html'));
        return;
    }

    // 使用SSE
    $sev = SwooleEventSource::make($response);

    while(true) {
        
        $sev->json([
            'message' => 'swoole消息'. rand(1, 100),
            'time' => time(),
        ]);
        $back = time() <= 1713952254;
        // 超过时间就done【代表发送完毕】
        $back or $sev->done();

        if ($sev->aborted()) {
            // 客户端应当对stop事件进行监听处理
            $sev->write('结束了', 'stop');
            break;
        }

        Coroutine::sleep(1);
    }
});
$http->start();