SvelteKit如何在Store中调用+server.ts接口获取服务器列表?
Svelte Store调用+server.ts接口的错误修复方案
问题背景
在Svelte项目中,尝试通过Store调用src/routes/api/+server.ts接口获取服务器列表并展示时,出现两个错误:
Failed to parse URL from /api(URL解析失败)Cannot read properties of undefined (reading 'length')(读取未定义属性length)
错误原因及修复步骤
1. 解决Failed to parse URL from /api错误
原因:代码在服务端渲染(SSR)阶段执行时,相对路径/api缺少base URL上下文,导致fetch无法解析正确的URL;且Store中的fetchServers可能在服务端被执行,服务端环境没有浏览器的URL上下文支撑。
修复方案(二选一即可):
方案A:传入SvelteKit提供的fetch函数
- 修改
serverSection.svelte,将组件获取到的SvelteKit专属fetch传给Store方法:
<script lang="ts"> export let bgImage: string export let logo: string export let text: string import { fetchServers, serversStore } from '../stores/servers' import Server from './server.svelte' import { page } from '$app/stores' fetchServers($page.fetch) </script>
- 修改
servers.ts,接收外部传入的fetch函数:
import { writable, type Writable } from 'svelte/store' export const serversStore: Writable<any[]> = writable([]) export const fetchServers = async (fetchFn = fetch) => { const response = await fetchFn('/api', { method: 'GET', headers: { 'content-type': 'application/json', accept: 'application/json', }, }) const data = await response.json() serversStore.set(data) }
方案B:确保仅在客户端执行fetch
利用Svelte的onMount钩子,限制fetchServers仅在浏览器环境运行:
<script lang="ts"> export let bgImage: string export let logo: string export let text: string import { fetchServers, serversStore } from '../stores/servers' import Server from './server.svelte' import { onMount } from 'svelte' onMount(() => { fetchServers() }) </script>
2. 解决Cannot read properties of undefined (reading 'length')错误
原因:
serversStore初始值为undefined(writable()未传初始值),组件遍历数据时会读取undefined的length属性;fetchServers中直接将Response对象存入Store,而非接口返回的JSON数组,Response对象本身没有length属性。
修复方案:
- 修改
servers.ts,设置初始空数组并解析响应为JSON:
import { writable, type Writable } from 'svelte/store' // 初始化为空数组,避免undefined报错 export const serversStore: Writable<any[]> = writable([]) export const fetchServers = async (fetchFn = fetch) => { try { const response = await fetchFn('/api', { method: 'GET', headers: { 'content-type': 'application/json', accept: 'application/json', }, }) if (!response.ok) { throw new Error(`请求失败: ${response.status}`) } // 解析响应为JSON数组 const serverData = await response.json() serversStore.set(serverData) } catch (error) { console.error('获取服务器列表失败:', error) serversStore.set([]) // 出错时设置空数组,避免组件报错 } }
- 组件中遍历数据时,直接使用
each即可(因初始值为空数组,不会触发length读取错误):
<!-- serverSection.svelte 中的HTML部分 --> <div> {#each $serversStore as server} <Server {...server} /> {/each} </div>
内容的提问来源于stack exchange,提问作者Maxi Jabase
相关产品推荐
相关产品推荐

