 与 NOTIFY 实现数据库内频道通知?)
PGlite 如何用 .listen() 与 NOTIFY 实现数据库内频道通知【免费下载链接】pgliteEmbeddable Postgres with real-time, reactive bindings.项目地址: https://gitcode.com/GitHub_Trending/pg/pglite在 PGlite 中实现「某个事件发生后JavaScript 端立刻收到一条消息」这类需求不需要自己轮询数据表Postgres 原生的LISTEN/NOTIFY机制在 PGlite 里被封装成了.listen()方法。执行NOTIFY语句后订阅了对应频道的回调函数会收到 payload 字符串。这套 API 在 Node、Bun、Deno 和浏览器中都可用PGlite 同时支持这两个运行环境本文走一遍从安装、订阅频道、发送通知到取消订阅的完整路径以及如何验证通知确实到达了回调。准备条件安装并创建实例先用包管理器安装 PGlite以 npm 为例其他包管理器见 Getting startednpm install electric-sql/pglite创建实例。不带参数时是内存数据库适合演示和开发import { PGlite } from electric-sql/pglite const pg new PGlite()如果需要持久化dataDir支持不同存储后端详见 PGlite API 文档file://或不加前缀文件系统存储Node 和 Bun 可用idb://IndexedDB 存储浏览器可用memory://内存临时存储全平台可用。例如浏览器中持久化到 IndexedDBnew PGlite(idb://my-pgdata)。也可以改用静态方法await PGlite.create(options)它会额外等待.waitReady的 Promise确保数据库完全初始化后再返回实例。不过查询方法本身在数据库未就绪时会自动等待waitReady完成所以一般不必手动等待。主路径用 .listen() 订阅频道并接收 NOTIFY.listen()的签名来自 API 文档.listen(channel: string, callback: (payload: string) void): Promise() Promisevoid它订阅一个pg_notify频道回调接收通知的 payload字符串并返回一个取消订阅函数。.listen()会自动处理订阅这一点与后文的onNotification不同。一条最短的完整示例可以直接在 Node 中运行import { PGlite } from electric-sql/pglite const pg new PGlite() // 订阅频道 test回调接收 payload const unsub await pg.listen(test, (payload) { console.log(Received:, payload) }) // 向频道 test 发送一条带 payload 的通知 await pg.query(NOTIFY test, Hello, world!) // 确认收到通知后取消订阅 await unsub() // 干净地关闭数据库 await pg.close()回调是异步被触发的NOTIFY语句执行完成后通知会经由 Postgres 通知机制到达回调而不是同步在query返回的同时调用。官方浏览器示例 notify.html 因此在每步操作之间显式等待了 500ms用于让日志按顺序展示。官方浏览器示例的完整流程值得注意最后一步await unsub() await pg.query(NOTIFY test, Will not be received!)取消订阅后再NOTIFY这条通知不会到达回调——这是判断取消订阅是否生效的直接依据。验证通知是否到达三个层级的验证方式都在仓库里控制台输出示例中的console.log(Received:, payload)会打印收到的 payload文档示例输出为Received: Hello, world!文档示例实际 payload 取决于你NOTIFY传入的内容。官方测试断言notify.test.ts 中的notify用例订阅频道后执行await pg.exec(NOTIFY test, 321)并断言回调收到的payload严格等于321unlisten用例则断言取消订阅后再NOTIFY不会触发回调。浏览器示例页面examples 列表 中的 Notify and Listen 对应 packages/pglite/examples/notify.html页面会输出收到的消息日志可以直观看到订阅期内收到两条消息、取消订阅后的那条没有到达。取消订阅的两种方式listen返回的 unsubscribe 函数await unsub()只移除当前这个回调。.unlisten(channel, callback?)提供callback时只移除该回调不提供时移除该频道上的所有回调。签名.unlisten(channel: string, callback?: (payload: string) void): Promisevoid。一个回调可能多次调用.listen()订阅同一频道每次调用都会追加一个订阅此时用带callback参数的.unlisten()精确移除而不是清掉整个频道。替代路径onNotification 接收所有频道的通知如果不想按频道逐个注册回调可以用onNotification挂一个全局处理器它会收到 Postgres 发来的所有通知回调签名是(channel: string, payload: string) voidpg.onNotification((channel, payload) { console.log(channel, payload) }) await pg.exec(LISTEN test) await pg.exec(NOTIFY test, 123)API 文档明确警告onNotification只添加事件处理器并不执行订阅必须自己先用LISTEN channel_name订阅频道通知才会到达。这与.listen()内部自动完成订阅是主要区别。不再需要时用offNotification(callback)移除对应处理器。频道命名规则与易错点.listen()的频道名遵循 Postgres 的标识符规则这也是官方测试专门覆盖的行为见 notify.test.ts 的 check notify case sensitivity special chars as Postgresql 用例不加双引号时频道名会被转为小写pg.listen(TeStiNG)等价于pg.listen(testing)NOTIFY PostgresDefaultLower与NOTIFY postgresdefaultlower命中的是同一频道。加双引号时区分大小写pg.listen(TeST)与pg.listen(test)是不同频道大小写不同的双引号频道名之间不会互相收到通知。含空格或特殊字符的频道名必须加双引号pg.listen(Quoted Channel With Spaces)和pg.listen(testme)可以正常订阅而pg.listen(Unquoted Channel With Spaces)或pg.listen(testme)不带引号会直接抛错对应的NOTIFY语句同样会失败。如果你的业务里频道名来自变量建议统一用双引号包裹并保证LISTEN/NOTIFY两端引号用法一致避免因为隐式小写化或非法字符导致「发了通知但收不到」。小结与延伸主路径是.listen(channel, callback)订阅 NOTIFY channel, payload发送取消订阅用返回的unsub()或.unlisten()验证依据是回调收到的 payload 与你NOTIFY的内容一致、取消订阅后不再收到。需要跨频道统一处理时用onNotification但记得它不替你LISTEN。更完整的接口说明见 PGlite API 文档可直接运行的浏览器示例见 packages/pglite/examples/notify.html行为断言见 packages/pglite/tests/notify.test.ts。【免费下载链接】pgliteEmbeddable Postgres with real-time, reactive bindings.项目地址: https://gitcode.com/GitHub_Trending/pg/pglite创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考