ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Svelte Query useIsFetching 详解:响应式统计正在请求中的查询数量

Svelte Query useIsFetching 详解:响应式统计正在请求中的查询数量 Svelte Query useIsFetching 详解响应式统计正在请求中的查询数量【免费下载链接】query Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.项目地址: https://gitcode.com/GitHub_Trending/qu/queryuseIsFetching是 Svelte Querytanstack/svelte-query提供的一个响应式工具函数用于统计当前正在向后端发起请求fetching的查询数量并返回一个可直接在 Svelte 模板与逻辑块中使用的响应式值。它非常适合实现全局加载指示器、刷新进度提示等跨查询共享 UI 状态在 Svelte Query 参考文档 中作为核心函数 API 收录。读完本文你将掌握它的签名、参数过滤规则、返回值语义以及它从QueryClient到QueryCache的完整底层实现链路。函数签名与核心能力useIsFetching的完整类型签名如下function useIsFetching(filters?, queryClient?): ReactiveValuenumber;它的定义位于 packages/svelte-query/src/useIsFetching.svelte.ts#L40并通过 packages/svelte-query/src/index.ts#L28 从tanstack/svelte-query包对外导出export { useIsFetching } from ./useIsFetching.svelte.js它接收两个可选参数——filters用于缩小统计范围的QueryFilters与queryClient自定义客户端实例返回一个ReactiveValuenumber。与 React Query 的useIsFetching返回普通数字不同Svelte 版本返回的是 Svelte 5 运行时的响应式容器对象读取其中的.current属性即可拿到当前正在请求的查询数量且读取行为会被 Svelte 的响应式系统自动追踪。参数详解filters?QueryFiltersfilters是QueryFiltersreadonly unknown[]类型用于收窄统计哪些查询的范围。省略该参数时统计所有正在请求的查询。QueryFilters定义于 packages/query-core/src/utils.ts#L27其字段如下字段类型说明typeall \| active \| inactive只统计 active 查询、inactive 查询或全部查询exactboolean是否精确匹配queryKey默认前缀匹配predicate(query: Query) boolean自定义谓词函数逐个过滤查询queryKeyTQueryKey \| TuplePrefixesTQueryKey按查询键匹配支持前缀匹配staleboolean只统计过期stale或未过期的查询fetchStatusFetchStatus按请求状态过滤FetchStatus取值为fetching \| paused \| idle定义于 packages/query-core/src/types.ts#L665最常用的写法是传入queryKey进行前缀匹配。例如useIsFetching({ queryKey: [posts] })会统计所有以[posts]开头的查询键对应的请求若需精确匹配可加exact: true。也可以通过predicate做更细粒度的判断例如只统计某个特定数据源的请求。queryClient?QueryClientqueryClient用于指定自定义的QueryClient实例。省略时useIsFetching会通过 Svelte 的 context 机制获取最近的QueryClient。这一解析逻辑位于 packages/svelte-query/src/useQueryClient.tsexport function useQueryClient(queryClient?: QueryClient): QueryClient { if (queryClient) return queryClient return getQueryClientContext() }因此在大多数场景下只要组件树外层通过QueryClientProvider或setQueryClientContext注入了客户端直接调用useIsFetching()即可。只有需要绕过 context例如测试环境、独立模块时才显式传入第二个参数。返回值 ReactiveValuenumber 的语义返回的ReactiveValuenumber是 Svelte Query 对 Svelte 5 响应式运行时的封装。要读取当前统计值必须访问.currentscript langts import { useIsFetching } from tanstack/svelte-query const isFetching useIsFetching() /script {#if isFetching.current} divQueries are fetching in the background.../div {/if}其实现位于 packages/svelte-query/src/containers.svelte.ts#L8-L21export class ReactiveValueT implements BoxT { #fn #subscribe constructor(fn: () T, onSubscribe: Subscriber) { this.#fn fn this.#subscribe createSubscriber((update) onSubscribe(update)) } get current() { this.#subscribe() return this.#fn() } }每次访问current都会触发两件事调用createSubscriber来自svelte/reactivity建立的订阅逻辑把当前读取位置注册为queryCache的监听者执行内部的fn()实时计算并返回当前的 fetching 数量。当queryCache后续发生变更查询开始/结束请求时订阅回调会通知 Svelte 的响应式系统让所有读取过current的模板表达式自动重新求值——这正是useIsFetching能响应式跟随请求状态变化的根本原因。使用示例场景一按 queryKey 前缀过滤展示局部刷新提示原文档给出的典型用法是只关心某个数据域内的请求。以下代码统计所有以[posts]为前缀的查询是否正在请求并据此显示刷新提示script langts import { useIsFetching } from tanstack/svelte-query // How many queries matching the posts prefix are fetching? const isFetchingPosts useIsFetching({ queryKey: [posts] }) /script {#if isFetchingPosts.current} spanRefreshing posts.../span {/if}场景二全局加载指示器不传任何参数时useIsFetching统计的是 queryCache 中所有正在请求的查询包括后台静默刷新、预取等不在当前屏幕上渲染的查询。这非常适合做应用级的全局进度指示script langts import { useIsFetching } from tanstack/svelte-query const isFetching useIsFetching() /script {#if isFetching.current} divQueries are fetching in the background.../div {/if}注意它与单个查询结果里的isFetching语义不同useQuery返回的isFetching只反映该查询自身是否在请求而useIsFetching是跨查询的聚合视角。场景三组合过滤条件实际项目中可以组合多个过滤字段精确控制统计口径。例如只统计 active有组件正在观察且已过期stale的查询script langts import { useIsFetching } from tanstack/svelte-query const isFetchingActiveStale useIsFetching({ type: active, stale: true, }) /script {#if isFetchingActiveStale.current} pActive stale queries are refetching…/p {/if}也可以配合enabled条件查询参考 createQuery观察请求的生命周期请求发起时计数 1请求完成时归零。底层实现原理useIsFetching的完整实现非常精简核心只有几行packages/svelte-query/src/useIsFetching.svelte.ts#L40-L51export function useIsFetching( filters?: QueryFilters, queryClient?: QueryClient, ): ReactiveValuenumber { const client useQueryClient(queryClient) const queryCache client.getQueryCache() return new ReactiveValue( () client.isFetching(filters), (update) queryCache.subscribe(update), ) }整个数据流可以拆解为三个环节1. 获取客户端与缓存。通过useQueryClient(queryClient)拿到实际使用的QueryClient再通过client.getQueryCache()取得底层的QueryCache。QueryCache是查询实例的存储与订阅中心。2. 计算 fetching 数量。每次响应式求值时调用client.isFetching(filters)。该方法定义于 packages/query-core/src/queryClient.ts#L109-L114isFetchingTQueryFilters extends QueryFiltersany QueryFilters( filters?: TQueryFilters, ): number { return this.#queryCache.findAll({ ...filters, fetchStatus: fetching }) .length }可以看到无论调用者是否传入过滤条件isFetching都会强制附加fetchStatus: fetching然后在 queryCache 中查找所有满足条件的查询并返回数量。3. 订阅变更。构造ReactiveValue时传入(update) queryCache.subscribe(update)。每当 queryCache 中任何查询的状态发生变化例如请求开始、请求结束、缓存被写入QueryCache都会触发订阅回调从而驱动所有读取过isFetching.current的 Svelte 表达式重新执行。一个值得注意的细节fetching 与 paused 的区分FetchStatus有三种取值fetching | paused | idle见 packages/query-core/src/types.ts#L665。由于isFetching强制按fetchStatus: fetching过滤处于paused例如网络离线而暂停请求状态的查询不会被计入统计结果。这一点从源码逻辑可以直接推断只有真正在发请求的查询才会被findAll选中。测试验证请求开始与结束时的计数变化仓库中为useIsFetching提供了对应的测试组件与用例位于 packages/svelte-query/tests/useIsFetching/useIsFetching.svelte.test.ts。测试组件 Base.svelte 中先通过setQueryClientContext(queryClient)注入客户端再创建一个受ready开关控制的查询与一个useIsFetching()script langts import { setQueryClientContext } from ../../src/context.js import { createQuery, useIsFetching } from ../../src/index.js setQueryClientContext(queryClient) let ready $state(false) const query createQuery(() ({ queryKey: queryKey(), queryFn: () sleep(10).then(() test), enabled: ready, })) const isFetching useIsFetching() /script button onclick{() (ready true)}setReady/button divisFetching: {isFetching.current}/div测试用例验证了计数的动态变化useIsFetching.svelte.test.ts#L19-L31初始状态显示isFetching: 0点击按钮启用查询后enabled: true触发请求计数变为1查询完成10ms 的sleep结束后计数回到0。这直接印证了查询开始请求 → 计数 1请求结束 → 计数归零的响应式行为也说明useIsFetching会跨查询生命周期持续跟踪状态。常见问题与注意事项读取时一定要用.currentuseIsFetching返回的是ReactiveValue容器而非原始数字忘记访问.current会在模板中拿到对象本身无法正确渲染。默认前缀匹配传入queryKey时默认按前缀匹配[posts]会匹配[posts, 1]、[posts, detail]等需要精确匹配时显式设置exact: true。不区分屏幕内外不带参数调用时后台刷新、预取prefetch等不在当前组件观察范围内的请求也会被计入这正是设计上用于全局加载指示的原因。自定义 QueryClient 场景多客户端架构下可通过第二个参数显式指定QueryClient否则始终使用最近 context 中的实例。paused 查询不计入网络离线等导致暂停的请求不会让计数 1因为底层强制按fetchStatus: fetching过滤。小结useIsFetching用极简的 API 抽象了跨查询聚合请求状态这一常见需求参数层通过QueryFilters提供前缀匹配、精确匹配、谓词过滤等丰富的统计口径返回值层借助ReactiveValue与queryCache.subscribe实现了完全响应式的更新链路底层则由QueryClient.isFetching统一收敛到findAll({ fetchStatus: fetching })。无论是页面级正在刷新提示、应用级全局加载条还是多查询协同的业务场景它都是 Svelte Query 生态中最直接的解决方案。【免费下载链接】query Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.项目地址: https://gitcode.com/GitHub_Trending/qu/query创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表