@cplieger/ sse (英语)
一个Server-Sent-Events客户端,它完全恢复到它停止的地方,注意到一股死流,并在睡眠后调和.
类型脚本的一半 github.com/cplieger/go/sse/v2 (英语)说电线走 sse 软件包服务:每个帧都带有 epoch:offset 光标,每个连接打开一个 Hello , 上面写着光标是否被遵守, 而客户端将两者都变成一个可以信任的应用程序在页面隐藏、 电话锁或网络更改之间。 一个本地人 EventSource 无法设置请求头, 无法告诉空闲的静音流, 无法按自己的日程重新连接到任意 Last-Event-ID 它最后一次看到; 此客户端拥有连接 fetch 财务报告和审定财务报表 ReadableStream 相反, 显示它所持有的光标, 测量字节上的活度, 一分钟后关闭隐藏的标签流, 并在返回时重新打开, 用完全的焦距退后, 并在应用程序询问服务器时按住进入的帧 。 它没有运行时间依赖关系,DOM阅读器(document.visibilityState, (中文(简体) ), navigator.onLine)是可注射的,所以相同的运行时间在节点运行来对抗Go测试固定.
安装
npx jsr add @cplieger/sse
# or
npm i @cplieger/sse
使用量
import { createStream, createVersionMap } from "@cplieger/sse";
const versions = createVersionMap();
const stream = createStream({
url: "/api/events",
headers: { "SSE-Client": profileTag },
alive: { url: "/api/alive" },
versions,
onFrame: (frame) => {
applyToStore(frame.type, frame.data);
},
revalidate: async (ctx) => {
// Runs once per hello and once per wake, never concurrently. Every fetch in
// here takes ctx.signal; ctx.full means the map was cleared, so skip the digest.
await reconcile(versions.snapshot(), ctx);
},
onLifecycle: (ev) => {
log.debug("sse", ev);
},
});
stream.start();
每个连接的第一个框架是问候:它命名了服务器的时代、环的地板和头、保存的间隔和事件名称,以及客户端显示的光标是否恢复;一个问候 wire 已经在外面 [minWire, maxWire] (两者都默认为包 WIRE与 a 结束连接 wire_unsupported 记录和保存光标.
客户端将其光标保留为 epoch:offset,作为 Last-Event-ID 每个连接上, 并且只在帧被传送到 onFrame,因此一个空隙后重新连接要么通过无法覆盖空隙的打招呼来准确重放被忽略的帧,要么通过报告进行回放,应用程序可以调和而不是信任回放.
stream.state() 返回 a StreamState: 连接类型( u)stopped, (中文(简体) ), connecting, (中文(简体) ), open, (中文(简体) ), backoff, (中文(简体) ), offline 或者说 hidden_closed),它的生成和尝试,以及那种作用的读取,例如: visible, (中文(简体) ), online问候你 keepaliveMs 当一个逆流结束的时候。 软件包输出工厂、电线辅助器以及它们取用和返回的类型;其分解器、还原器和制表折叠是内部的.
虽然 revalidate 运行,进入的帧在结算后会按顺序进行并交付;运行是单飞行,第二个原因队列最多会再运行一跑,一个被持有的队列过2000帧或64 MiB会结束连接,所以下一个连接会从光标恢复.
与 alive 设置,每个保存(或每个保存) everyBeats-th)被确认为: POST 带有流头的 URL,所以一个服务器侧面的存在表按键 SSE-Client 查看哪些客户端仍在阅读;失败的确认报告为 alive_ack 记录.
一个401结束会话的流而不是重试:一个401在流请求上,一个活的确认,或者来自一个 revalidate 拒绝 { status: 401 } 停止流出一个 auth_lost 记录 route 实值 stream, (中文(简体) ), alive 或者说 digest。一个标签的自流和工人主机的行为相同,主机将记录传递到每一个标签。 任何其它状态都退后并重新连接.
createWorkerHost 在 a 内运行每个浏览器配置文件的一个流 SharedWorker,以及 attachToWorker 以 a 连接每个标签 MessagePort,将标签的能见度和网络读取值折叠为该连接 SharedWorker 或工人从不回答,标签会回到自己的流中,并报告开关。 这个 fallback 选项返回 a TabFallback页:1 createStream 成果与 versions 地图和 headers 记录它是建立在, 这是让 TabAttachment 在两种模式中工作相同. observe(subject, version, epoch) 向主机的版本映射或倒计时器上报告标签; reconnect({ resetCursor }) 重新连接标签所附的流; setTag(tag) 呈现新的 SSE-Client a. 重联值,写入主机头或后退;以及 detach("logout") 结束配置的流 。 标签上写着 tag 在第一个连接之前输入掉头头,所以消费者永远不会填充 SSE-Client 自己来.
主机呈现第一个非空标签标签,标签标签加附并替换,重新连接一次,当后继附件或 setTag 带有不同的标记;空标记被忽略.
主持人 revalidate(ctx, tabs) 身体为简介做一个文摘,并将判决通过每个分页 tabs.run(ctx, { changed, removed })所以每个标签 revalidate 收到一个 TabRevalidateContext 携带 changed 财务报告和审定财务报表 removed 除了它自己 signalA级 state 信件在 lifecycle 记录相同的过渡,所以 attachment.state()页:1 StreamState,在处理器内是电流,而连接在活流上的标签接收 state 之后为 a tab_attached 记录命名该状态.
软件包类型检查 lib: ["ESNext", "WebWorker"] 以及DOM lib(《宪法》)之下tsconfig.worker.json 所以消费者的工人可以进口 createWorkerHost 仅限工人参加:DOM的能见度和在线来源 document 财务报告和审定财务报表 window 结束 globalThis 在他们不在场的情况下,他们是疏忽的.
onLifecycle 接受每个州的改变和诊断 LifecycleEvent 记录state, (中文(简体) ), hello, (中文(简体) ), watchdog, (中文(简体) ), reset, (中文(简体) ), revalidate, (中文(简体) ), hidden_closed, (中文(简体) ), alive_ack, (中文(简体) ), worker_dead 以及联盟的其余部分),即表层来记录和计算.
浏览层
Response.body 作为可读溪流(Firefox 65,Chrome 43,Safari 10.1), AbortSignal.reason (火狐97,Chrome 98,Safari 15.4), visibilitychange (Chrome 62, Firefox 56, Safari 14.1), (中文(简体) ), pagehide 财务报告和审定财务报表 pageshow,以及 BigInt (Chrome 67,Firefox 68,Safari 14). AbortSignal.any 不使用;两个信号由手构成. SharedWorker 仅由工人主机需要,而不在地板上:在没有(Chrome for Android before 148, 三星互联网)的情况下,标签会通过倒计时运行自己的流.
完整文档
Go 服务器 API 在 仓库读取器中枢选项和存在钩 运行中枢和你好的判决和摘要 电线合同。共享计时常数 timing.json。 。 。 .
免责声明
这个项目是精心设计的,遵循安全最佳做法,但打算供个人/自发使用。 不保证生产环境的适宜性. 自己冒险使用.
这个项目是利用AI辅助工具,使用 克劳德, (中文(简体) ), 常规,以及 基罗人类维护者界定建筑、监督实施和作出所有最后决定.
许可证
阿帕奇2.0 (英语). 见 自由主义。 。 。 .