SvelteKit多加载源自动重试加载Spinner实现方案咨询
SvelteKit 加载Spinner + 自动重试最佳实践
核心思路
- 用Svelte响应式状态统一控制Spinner的显示/隐藏
- 封装通用重试工具函数,避免重复编写重试逻辑
- 将地图初始化、数据请求拆分为独立异步任务,通过Promise串联确保执行顺序
具体实现步骤
1. 定义响应式状态
在组件中声明控制Spinner的状态,同时可添加错误提示状态提升用户体验:
<script> import { onMount } from 'svelte'; // 控制Spinner显示状态 let isLoading = true; // 可选:显示加载失败提示 let errorTip = ''; </script> <!-- 加载Spinner组件 --> {#if isLoading} <div class="loading-spinner"> <div class="spinner-icon"></div> <p>{errorTip || '加载中...'}</p> </div> {/if} <!-- MapLibre地图容器 --> <div id="map-container" class="map-box"></div>
2. 封装通用重试函数
写一个通用异步重试工具,支持自定义重试延迟,默认5秒;无限重试直到任务成功:
/** * 异步任务自动重试工具 * @param {Function} fn - 需要重试的异步函数 * @param {number} delay - 重试间隔(毫秒),默认5000 */ async function retryAsync(fn, delay = 5000) { while (true) { try { return await fn(); } catch (err) { console.error('加载失败,即将重试:', err); errorTip = '加载失败,5秒后重试...'; // 等待指定延迟后再次执行任务 await new Promise(resolve => setTimeout(resolve, delay)); } } }
3. 封装MapLibre地图加载函数
将地图初始化逻辑封装为Promise,把事件回调转为异步逻辑:
async function initMapLibre() { return new Promise((resolve, reject) => { const map = new maplibregl.Map({ container: 'map-container', style: 'https://demotiles.maplibre.org/style.json', // 替换为你的地图样式URL center: [116.397428, 39.90923], // 替换为你的初始中心点 zoom: 10 }); // 地图加载成功时resolve map.on('load', () => resolve(map)); // 地图加载失败时reject map.on('error', (error) => reject(error)); }); }
4. 封装额外数据请求函数
将数据fetch逻辑封装为独立异步函数,统一错误处理:
async function fetchExtraDataset() { const response = await fetch('你的数据API地址'); if (!response.ok) { throw new Error(`请求失败,状态码: ${response.status}`); } return await response.json(); }
5. 串联加载流程并更新状态
在onMount中调用重试函数,按顺序执行地图加载、数据请求,完成后关闭Spinner:
onMount(async () => { try { // 先重试加载地图,直到成功 const map = await retryAsync(initMapLibre); // 地图加载完成后,继续重试加载额外数据 const extraData = await retryAsync(fetchExtraDataset); // 所有加载任务完成,关闭Spinner isLoading = false; errorTip = ''; // 这里可以添加地图数据渲染逻辑,比如添加自定义图层 map.addSource('custom-data', { type: 'geojson', data: extraData }); // 示例:添加填充图层 map.addLayer({ id: 'custom-layer', type: 'fill', source: 'custom-data', paint: { 'fill-color': '#888888', 'fill-opacity': 0.4 } }); } catch (finalError) { // 若设置了最大重试次数,可在这里处理最终失败的情况(本示例为无限重试,此分支不会触发) errorTip = '加载最终失败,请刷新页面重试'; isLoading = false; console.error('最终加载失败:', finalError); } });
6. 添加上样式(可选)
给Spinner和地图容器添加基础样式,提升视觉体验:
.loading-spinner { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: #ffffff; padding: 1.5rem 2rem; border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); display: flex; flex-direction: column; align-items: center; gap: 0.8rem; z-index: 9999; } .spinner-icon { width: 32px; height: 32px; border: 3px solid #f3f3f3; border-top: 3px solid #3498db; border-radius: 50%; animation: spin 1s linear infinite; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .map-box { width: 100%; height: 100vh; }
方案优势
- 逻辑复用:通用重试函数可复用在任何需要重试的异步任务中,减少冗余代码
- 状态可控:通过Svelte响应式状态自动绑定Spinner显示,无需手动操作DOM
- 流程清晰:Promise串联任务确保地图加载完成后才请求数据,符合业务逻辑
- 容错性强:自动重试直到任务成功,满足需求中持续重试的要求
内容的提问来源于stack exchange,提问作者Bojan Vukasovic
相关产品推荐
相关产品推荐

