我正在尝试使用 htmx 设置一个短暂的事件流处理程序。想象一下,例如,流式传输 chatgpt 响应或类似内容。该流将持续 10-30 秒,然后我预计它会耗尽。
有没有办法让 htmx 监听 SSE 事件类型并关闭 SSE 源作为响应?
我有一个笨重的解决方法,我有一个用于流终止事件类型的 htmx 侦听器,然后该侦听器向仅返回一个空 div 的端点发出请求,并将该 div 交换为原始侦听器,以防止它无休止地尝试重新连接到 SSE 源。
但我觉得我一定错过了一些东西,因为这看起来不太优雅。
这就是我现在拥有的,如下。它有效(大部分),但是有更好的吗?谢谢!
<div
id="chat-sse-listener"
hx-ext="sse"
sse-connect="{% url 'stream_test' %}"
>
{# This listens for the next token in the stream and appends it to the chat. #}
<div
sse-swap="message"
hx-target="#chat-message"
hx-swap="beforeend"
></div>
{# This listens for my custom EndOfStream SSE event and awkwardly replaces the entirely SSE listener with an empty div. #}
<div
hx-trigger="sse:EndOfStream"
hx-target="#chat-sse-listener"
hx-swap="outerHTML"
hx-get="{% url 'empty_div_response' %}"
></div>
</div>
<div id="chat-message"></div>
Run Code Online (Sandbox Code Playgroud)
更新:
经过一番尝试后,我有了一个稍微不那么尴尬(但仍然不是很好)的解决方案。我没有使用第二个侦听器和第二个事件类型,而是通过让服务器使用 htmx 的带外交换 API 传递 div 来结束流。然后使用该 div 来替换(从而删除)sse 侦听器。
代码:
async def __anext__(self):
await asyncio.sleep(0.25)
if self.story_tokens_queue.empty():
if self.sent_close_token:
raise StopAsyncIteration
else:
self.sent_close_token = True
# this div will be swapped, out-of-band, for the existing #chat-see-listener, effectively removing it
# and closing the SSE source on the client side
return 'data: <div id="chat-sse-listener" hx-swap-oob="true"></div>\n\n'
else:
token = self.story_tokens_queue.get().replace("\n", "<br/>")
return f"data: {token}\n\n"
Run Code Online (Sandbox Code Playgroud)
活动部件较少,但不如明确要求客户端关闭源那么清晰。我确信此时认为这需要额外的 JavaScript。
最后的后续工作 这是我在业余项目的制作过程中要做的事情。目前有效!
我的后端代码将其作为 SSE 流发送的最后一个令牌:
# second, we close the SSE listener on the client side
elif not self.sent_close_token:
self.sent_close_token = True
# this div will be swapped, out-of-band, for the existing #chat-see-listener, effectively removing
# it and closing the SSE source on the client side
return 'data: <div id="chat-sse-listener" hx-swap-oob="true"></div>\n\n'
Run Code Online (Sandbox Code Playgroud)
我的 HTML 看起来像这样:
<div
id="chat-sse-listener"
hx-ext="sse"
sse-connect="{% url 'chat_request_answer' id=chat_thread.id %}"
>
{# This listens for the next token in the stream and appends it to the chat. #}
<div
sse-swap="message"
hx-target="#sage-answer-{{ new_answer_id }}"
hx-swap="beforeend"
></div>
</div>
Run Code Online (Sandbox Code Playgroud)
我正在使用 htmx 1.9.6。
这种设置似乎对我有用。
| 归档时间: |
|
| 查看次数: |
310 次 |
| 最近记录: |