【问题标题】:Browser refresh not sending the last-event-id received as part of server sent response浏览器刷新不发送作为服务器发送响应的一部分收到的最后一个事件 ID
【发布时间】:2020-08-12 19:07:36
【问题描述】:

我正在尝试为使用的用户构建实时通知系统 服务器在 python 中发送事件。

我面临的问题是当我刷新浏览器时,这意味着 然后浏览器将尝试再次点击 EventSource url,并按照 文档它应该将 event.lastEventId 作为下一个标题的一部分发送 要求。每次刷新页面时我都会得到无。

<!DOCTYPE html>
<html>
    <header><title>SSE test</title></header>
    <body>
        <ul id="list"></ul>
        <script>
        const evtSource = new EventSource("/streams/events?token=abc");
        evtSource.onmessage = function(event) {
            console.log('event', event)
            console.log('event.lastEventId', event.lastEventId)
            const newElement = document.createElement("li");
            const eventList = document.getElementById("list");
            newElement.innerHTML = "message: " + event.data;
            eventList.appendChild(newElement);
        }
        </script>
    </body>
</html>

在服务器端

from sse_starlette.sse import EventSourceResponse
from asyncio.queues import Queue
from starlette.requests import Request

@event_router.get(
"/streams/events",
status_code=HTTP_200_OK,
summary='',
description='',
response_description='')
async def event_stream(request: Request):
    return EventSourceResponse(send_events(request))


async def send_events(request: Request):
    try:
        key = request.query_params.get('token')
        last_id = request.headers.get('last-event-id')
        print('last_id ', last_id) # this value is always None

        connection = Queue()
        connections[key] = connection

        while RUNNING:
            next_event = await connection.get()
            print('event', next_event)
            yield dict(data=next_event, id=next_event['id'])
            connection.task_done()
    except asyncio.CancelledError as error:
        pass

现在,根据 SSE 上的每个文档,当客户端重新连接或刷新 页面它将在标题中发送最后一个事件ID。我正在尝试阅读它 使用 request.headers.get('last-event-id'),但这始终为 null。

有关如何获取最后一个事件 ID 的任何指示都会有所帮助。还, 我如何确保以后不会发送相同的事件 用户已经看到了这些事件,因为我的整个逻辑将基于 服务器接收到的 last-event-id,所以如果读取后为 None Id 1 到 4 的事件,我将如何确保在服务器中我应该 即使用户的 last-event-id 为 null,也不会将这些发回

.

添加浏览器快照

第一张图片显示浏览器正在接收事件。 例如{alpha: abc, id:4}

第二张图片显示收到的事件是 正确设置 lastEventId。

【问题讨论】:

    标签: javascript python server-sent-events fastapi starlette


    【解决方案1】:

    我认为这是一种错误的理解。您从哪里得到“当客户端重新连接或刷新页面时,它将在标题中发送最后一个事件 ID”的部分。

    我的理解是最后一个 ID 是在重新连接时发送的。当您直接刷新页面时,这不会被视为断开连接和重新连接。您将完全重新启动整个页面,并从浏览器与服务器建立全新的 SSE 连接。请记住,例如,您的 SSE 是否有某个请求参数,这可能是由页面上的某些内容驱动的。您可以从同一个“页面”打开两个选项卡,但将不同的项目放入页面中,这会导致此请求参数在您的 SSE 中有所不同。它们完全是两个不同的 SSE 连接。一个不会影响另一个,只是如果你有太多浏览器可以达到最大连接限制。同样,如果您单击刷新,这就像正在创建一个新选项卡。这是一个全新的连接。

    【讨论】:

    • 在网络应用程序中使用 sse 对登录用户进行实时更新是否有任何最佳实践?我不想在重负载时使用套接字来利用过多的服务器资源。
    • 如果你搜索的话,那里的数量相当可观。如果您的基础架构支持 HTTP2,那么在我看来,这通常是最好的选择。但是没有必要让 SSE 启动并运行。最佳实践始终必须满足您的特定需求。
    猜你喜欢
    • 2016-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-30
    • 2019-03-08
    • 1970-01-01
    • 2014-11-15
    相关资源
    最近更新 更多