SvelteKit组件onMount内调用session.subscribe报错原因咨询
SvelteKit中session.subscribe调用报错原因解析
复现代码如下:
<script> import {onMount} from 'svelte'; import {session} from "$app/stores" import {writable} from 'svelte/store'; const store = writable('some value'); let value = null onMount(() => { // 自定义普通store放在onMount里订阅可正常运行 // return store.subscribe( (storeValue) => {value = storeValue}); // SvelteKit内置session store放在onMount里订阅会抛错 // return session.subscribe( (sessionValue) => {value = sessionValue}); // 报错信息:Uncaught (in promise) Error: Function called outside component initialization }); </script>
测试场景:上述代码写在SvelteKit项目的普通Svelte组件(非路由/页面组件)内,将
session.subscribe移到onMount外部即可正常运行。
报错根因
- 你用
writable自行创建的store是完全独立的通用store,不依赖Svelte组件运行时上下文,不管在什么时机调用subscribe都能正常工作。 - SvelteKit从
$app/stores导出的session(以及同模块下的page、navigating、updated等内置store)属于上下文绑定型store,实现逻辑强依赖组件初始化阶段注入的组件上下文:- Svelte组件执行顶层
<script>代码的阶段就是组件初始化阶段,此时Svelte运行时会把当前组件实例、上下文信息暂存在全局运行时变量中,供所有上下文相关API调用。 - 顶层脚本执行完、组件完成初始渲染挂载到DOM之后,才会触发
onMount回调,这时候组件初始化流程已经结束,全局运行时里暂存的当前组件上下文已经被清空。 session.subscribe内部自带调用时机校验,一旦检测到当前不在组件初始化阶段、拿不到有效组件上下文,就会抛出你看到的Function called outside component initialization错误。
- Svelte组件执行顶层
- 把订阅逻辑移到
onMount外部就正常的原因很简单:顶层脚本的代码是在组件初始化阶段同步执行的,此时上下文校验可以顺利通过,订阅能正常注册,同时Svelte会在组件销毁时自动清理这个订阅,不会造成内存泄漏。 - 报错持续出现的原因:
onMount会在组件每次挂载时触发,每次触发都会执行session.subscribe、触发上下文校验失败,所以错误会反复抛出。
正确使用方式
不要在onMount、异步回调、定时器这类脱离组件初始化同步执行上下文的位置,直接调用SvelteKit内置store的subscribe方法。直接在顶层脚本完成订阅,或者用Svelte自带的自动订阅语法$session读取值即可。
内容的提问来源于stack exchange,提问作者ofeenee
相关产品推荐
相关产品推荐

