SvelteKit接入GraphQL订阅后报错Cannot read property 'executeQuery' of null
报错根因
- 执行顺序错误:代码中先调用了
query()、subscription()执行查询和订阅操作,之后才执行setClient()注入urql客户端实例,调用操作时urql获取到的客户端为null,触发空指针报错 - SSR兼容问题:SvelteKit服务端渲染阶段
process.browser为false,你定义的client变量值为null,服务端执行代码时urql读取不到可用的客户端实例也会触发该报错
修复方案
调整代码逻辑,将客户端初始化、实例注入、查询订阅的执行逻辑全部包裹在浏览器端判断中,同时调整执行顺序,先注入客户端再执行查询/订阅操作:
import { setClient, query, operationStore, subscription } from '@urql/svelte'; import { createClient, defaultExchanges, subscriptionExchange } from '@urql/svelte'; import { createClient as createWSClient } from 'graphql-ws'; // 用SvelteKit官方提供的browser变量判断环境,比process.browser更稳定 import { browser } from '$app/environment'; let tags, onTagUpdated; if (browser) { // 仅在浏览器端初始化ws客户端和urql客户端 const wsClient = createWSClient({ url: 'ws://localhost:5000/graphql', }); const client = createClient({ url: 'http://localhost:5000/graphql', exchanges: [ ...defaultExchanges, subscriptionExchange({ forwardSubscription: (operation) => ({ subscribe: (sink) => ({ unsubscribe: wsClient.subscribe(operation, sink), }), }), }), ], }); // 先注入客户端实例 setClient(client); // 再初始化操作仓库、执行查询和订阅 tags = operationStore(`query {tags{tagName value}}`); onTagUpdated = operationStore(`subscription {onTagUpdated{tagName value}}`); query(tags); subscription(onTagUpdated); if($tags.fetching) { console.log("loading"); } else { console.log($tags.data); } }
如果需要在页面模板中使用$tags或者$onTagUpdated的数据,记得在模板中加上非空判断或者浏览器环境判断,避免服务端渲染时报错。
内容的提问来源于stack exchange,提问作者Gajaruban Jeyakumar
相关产品推荐
相关产品推荐

