ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

broadcastQueryClient 中不可 structured-clone 的数据导致跨标签页不同步怎么排查?

broadcastQueryClient 中不可 structured-clone 的数据导致跨标签页不同步怎么排查? broadcastQueryClient 中不可 structured-clone 的数据导致跨标签页不同步怎么排查【免费下载链接】query Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.项目地址: https://gitcode.com/GitHub_Trending/qu/query当你用tanstack/query-broadcast-client-experimental的broadcastQueryClient让同源same origin的多个标签页/窗口共享QueryClient状态时可能出现一种特定现象某一个 query 的更新没有同步到其他标签页而其他 query 都正常。文档明确给出了这个现象的成因如果缓存中某个 query 的数据、错误信息或 key 含有 structured-clone 算法无法序列化的值例如ReadableStream、File、函数、Vuereactive代理底层BroadcastChannel.postMessage调用就会对该 query 被拒绝这个 query 的跨标签页同步会被跳过缓存的其余部分仍正常广播见 broadcastQueryClient 文档。本文的排查目标就是确认这是不是这类问题并定位到具体是哪个 query、哪类值导致的。该包目前处于实验阶段minor 和 patch 版本都可能包含 breaking change如果要在生产使用文档建议锁定到 patch 级别的版本。确认现象是否指向 structured-clone 失败先核对两个前提排除配置问题两个标签页/窗口必须是同源且broadcastQueryClient使用了同一个broadcastChannel。broadcastChannel是文档中定义的“用于在标签页和窗口间通信的唯一通道名”默认值为tanstack-query不显式传时两边都用默认值一旦一侧显式改名而另一侧没有两个页面本来就不在一个通道上与 clone 失败无关。同步范围只受该 query 影响。文档说明失败时“Cross-tab sync is skipped for that query; the rest of the cache continues to broadcast normally”。如果你观察到的是全部 query 都不同步那不属于本文场景。在开发环境NODE_ENV非 production中没有配置onBroadcastError时默认行为是发出console.warn失败不会完全静默。源码index.ts中的警告模板为[broadcastQueryClient] Failed to broadcast {type} event for query {queryHash}. The query value could not be structured-cloned; cross-tab sync for this query was skipped.其中{type}和{queryHash}是运行时填入的事件类型updated/removed/added与 queryHash 字符串不是需要替换的占位符。控制台里看到这条警告加上附带的错误对象即可确认该 query 的广播因 structured-clone 失败被跳过。注意这个警告只在开发环境出现production 下默认不会有任何console.warn所以线上环境要靠下一步的回调。用 onBroadcastError 拿到错误和定位信息broadcastQueryClient的选项支持onBroadcastError回调文档 Options 一节interface BroadcastErrorEvent { type: updated | removed | added queryHash: string queryKey: QueryKey }回调接收两个参数errorpostMessage被拒绝时产生的错误对象和event上面这个事件对象。包内测试用new DOMException(DataCloneError, DataCloneError)模拟postMessage失败测试示例见 index.test.ts所以实际排查时错误对象通常就是 structured-clone 失败抛出的这类错误。文档给出的路由到错误追踪平台的示例需要引入sentry/browserimport * as Sentry from sentry/browser import { broadcastQueryClient } from tanstack/query-broadcast-client-experimental broadcastQueryClient({ queryClient, broadcastChannel: my-app, onBroadcastError: (error, event) { Sentry.captureException(error, { tags: { broadcastEvent: event.type }, extra: { queryHash: event.queryHash, queryKey: event.queryKey }, }) }, })没有接 Sentry 时同样的回调可以直接把error和event写进自己的日志event.queryKey用于定位是业务里哪个 queryevent.queryHash用于和开发环境默认警告里的 hash 相互印证event.type说明失败发生在哪类事件更新、移除、新增上。两个回调自身的边界文档与测试都有说明回调可以返回Promise其 rejection 会被内部捕获不会造成二次未处理的 rejection如果回调同步抛错或异步 reject开发环境会再发一条console.warn源码模板为[broadcastQueryClient] onBroadcastError threw while handling {type} for query {queryHash}.看到这条警告说明你排查用的回调自己出错了需要先修好回调再谈定位。检查 queryKey 指向的 query 里哪类值不可克隆拿到queryKey后按文档列出的范围检查该 query 的三处数据state.data、state.error、queryKey。文档明确给出的不可 structured-clone 的典型值包括ReadableStream——例如来自Response.body、流式 API 或 AI SDK 的响应流File对象函数框架代理对象如 Vue 的reactive。排查思路就是沿着 queryFn 的返回链路看queryFn 是否把流对象、文件对象、回调函数或框架 reactive 代理直接放进了返回数据里错误对象里是否携带了这类值比如把原始Response存进了 error以及 queryKey 本身是否含不可克隆的值。queryKey 一般会参与消息体广播added和updated消息都会携带queryKey它含不可克隆值时同样会导致该 query 的广播失败。验证与边界开发环境下确认问题 query 的广播恢复最直接的依据是不再出现 cross-tab sync for this query was skipped 的警告同时另一个标签页里该 query 的状态随事件变化——默认警告只在postMessage失败时发出警告消失即表示该 query 的广播不再被跳过。production 环境默认无任何警告输出所以线上要靠onBroadcastError的上报来持续监控排查完成后建议保留这个回调而不是移除。失败的影响面是单个 query其余缓存内容继续正常广播不要把“整站都不同步”当成此类问题的现象那种情况应回到通道名、同源这两个前提重新检查。该包是实验特性文档要求依赖方锁定 patch 级别版本以避免意外 breakage升级该包前后如有同步行为变化应先对照版本再排查代码。【免费下载链接】query Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.项目地址: https://gitcode.com/GitHub_Trending/qu/query创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表