You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Svelte中如何用Fetch轮询外部API?遇实现困境

解决方案:SvelteKit中实现API轮询并解决CORS问题

核心问题分析

  1. +page.server.js无法轮询:load函数仅在页面加载/刷新时执行一次,是一次性的服务器端数据获取逻辑,无法在其中通过setInterval实现持续轮询——函数执行完毕后上下文销毁,定时器不会持续运行。
  2. 客户端直接请求CORS错误:浏览器的同源策略限制前端直接跨域请求外部API,而服务器端请求不受此限制,因此需要通过本地API代理中转请求。

方案一:手动实现轮询(原生Svelte)

步骤1:创建服务器端代理路由

在src/routes/api/proxy/[uid]/+server.js中创建代理,让服务器端转发请求到外部API:

export async function GET({ params }) {
  // 服务器端请求外部API,无CORS限制
  const response = await fetch(`http://localhost:9595/api/v1/chrysalis/example?uid=${params.uid}`);
  const site = await response.json();
  
  // 返回处理后的数据给客户端
  return new Response(JSON.stringify(site[0]), {
    headers: { 'Content-Type': 'application/json' }
  });
}

步骤2:客户端实现轮询并清理定时器

在+page.svelte中,通过onMount启动轮询,同时用onDestroy清理定时器避免内存泄漏:

<script>
  import { onMount, onDestroy } from 'svelte';
  export let data; // 接收+page.server.js返回的初始数据
  
  // 用本地变量存储实时更新的数据
  let siteData = data;
  let intervalId;

  async function fetchLatestData() {
    // 请求本地代理路由,而非外部API
    const response = await fetch(`/api/proxy/${data.uid}`);
    siteData = await response.json();
  }

  onMount(() => {
    // 每隔3秒执行一次轮询(可根据需求调整间隔)
    intervalId = setInterval(fetchLatestData, 3000);
  });

  // 页面销毁时清除定时器
  onDestroy(() => {
    if (intervalId) clearInterval(intervalId);
  });
</script>

<!-- 用siteData渲染页面内容 -->
<div>
  <h2>UID: {siteData.uid}</h2>
  <p>分区数: {siteData.partitions}</p>
  <!-- 其他数据渲染逻辑 -->
</div>

方案二:用Svelte Query实现类SWR的自动轮询

如果习惯Next.js中SWR的用法,可以使用TanStack Svelte Query(原React Query的Svelte版本),它内置了轮询、缓存、错误处理等功能:

步骤1:安装依赖

npm install @tanstack/svelte-query

步骤2:全局配置QueryClient

在src/routes/+layout.svelte中添加全局Provider:

<script>
  import { QueryClient, QueryClientProvider } from '@tanstack/svelte-query';
  
  const queryClient = new QueryClient();
</script>

<QueryClientProvider client={queryClient}>
  <slot />
</QueryClientProvider>

步骤3:在页面中使用useQuery实现轮询

<script>
  import { useQuery } from '@tanstack/svelte-query';
  export let data;

  // 配置查询规则,自动轮询
  const { data: siteData } = useQuery({
    queryKey: ['site-data', data.uid], // 唯一标识查询,用于缓存
    queryFn: async () => {
      const response = await fetch(`/api/proxy/${data.uid}`);
      return response.json();
    },
    refetchInterval: 3000, // 轮询间隔(毫秒)
    initialData: data // 用+page.server.js的初始数据作为首屏内容
  });
</script>

<!-- 注意用$前缀访问Svelte Query的响应式数据 -->
<div>
  <h2>UID: {$siteData.uid}</h2>
  <p>分区状态: {$siteData.zStates}</p>
</div>

关键说明

  • 始终通过服务器端代理访问外部API:彻底规避浏览器CORS限制,同时可在代理层添加请求缓存、鉴权等逻辑。
  • 清理定时器:手动实现轮询时必须在页面销毁时清除定时器,防止内存泄漏。
  • Svelte Query的优势:无需手动管理定时器,自带缓存、重试、加载状态管理,适合复杂场景。

内容的提问来源于stack exchange,提问作者Luke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 15:10:28