如何在Svelte中处理HTTP请求过期及未捕获异常问题?
解决Svelte中AbortController中止请求的未捕获异常问题
1. 在API封装层统一捕获中止异常
既然所有请求都通过同一个类处理,直接在这个类的请求方法里统一加try/catch,专门过滤AbortError(浏览器中对应DOMException,name属性为AbortError)。这样所有组件调用API时,就不用各自重复处理中止异常了。
示例代码:
class ApiService { #abortControllers = new Map(); async get(url, options = {}) { // 中止同URL的未完成请求 this.#abortControllers.get(url)?.abort(); const controller = new AbortController(); this.#abortControllers.set(url, controller); try { const response = await fetch(url, { ...options, signal: controller.signal }); // 请求成功后清理控制器 this.#abortControllers.delete(url); return await response.json(); } catch (err) { // 仅忽略中止异常,其他错误正常抛出让上层处理 if (err.name === 'AbortError') { console.debug(`请求 ${url} 已被中止`); // 返回标识值让组件区分“中止”和“正常失败” return null; } throw err; } } }
之后在Svelte的effect里调用api.get()时,即使请求被中止,也只会返回null,不会抛出未捕获异常,组件可根据返回值自行判断后续逻辑。
2. 封装Svelte专用的请求Effect工具
如果不想修改API层,可以写一个通用的请求Effect工具,把中止异常的捕获逻辑封装进去,组件直接调用即可。
示例:
import { onMount, onDestroy } from 'svelte'; export function fetchWithAbortEffect(url, onSuccess) { let controller; const loadData = async () => { // 先中止上一次请求 controller?.abort(); controller = new AbortController(); try { const res = await fetch(url, { signal: controller.signal }); const data = await res.json(); onSuccess(data); } catch (err) { // 只过滤中止异常,其他错误抛出让组件处理 if (err.name !== 'AbortError') throw err; } }; onMount(loadData); onDestroy(() => controller?.abort()); }
组件中使用:
<script> import { fetchWithAbortEffect } from './utils.js'; let data; fetchWithAbortEffect('/api/list', (result) => { data = result; }); </script> {#if data} <ul> {#each data as item} <li>{item.name}</li> {/each} </ul> {:else} <p>加载中...</p> {/if}
3. 利用Svelte的{#await}语法过滤中止异常
对于组件内直接发起的请求,可以用Svelte的{#await}块结合条件判断,只处理非中止类的错误。
示例:
<script> import { ApiService } from './api.js'; const api = new ApiService(); let data; let loadPromise = api.get('/api/detail'); </script> {#await loadPromise} <p>加载中...</p> {:then result} {#if result} <div>{JSON.stringify(result)}</div> {/if} {:catch err} {#if err.name !== 'AbortError'} <p>加载失败:{err.message}</p> {/if} {/await}
这里通过:catch块过滤掉中止异常,避免在请求被中止时显示错误提示。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

