query
编辑此页面query
是一个高阶函数,设计用于创建一个与传入函数具有相同签名的新函数。
当这个新创建的函数首次使用特定参数集合调用时,原始函数会被执行,其返回值会被存储在缓存中并返回给创建函数的调用者。
下次使用相同参数调用创建的函数时(只要缓存仍然有效),它将返回缓存的值而不是重新执行原始函数。
query
可以在任何地方定义,然后在你的组件中通过 createAsync
使用。
然而,直接在 createResource
中使用 query
将不起作用,因为获取器不是响应式的,无法正确失效。
用法
const getUser = query( (id, options = {}) => fetch(`/api/users/${id}?summary=${options.summary || false}`).then((r) => r.json() ), "usersById");
getUser(123); // 触发对 /api/users/123?summary=false 的 GET 请求getUser(123); // 不会触发 GET 请求getUser(123, { summary: true }); // 触发对 /api/users/123?summary=true 的 GET 请求setTimeout(() => getUser(123, { summary: true }), 999000); // 最终会再次触发对 /api/users/123?summary=true 的 GET 请求
与预加载函数一起使用
与预加载函数一起使用:
import { lazy } from "solid-js";import { Route } from "@solidjs/router";import { getUser } from ... // 缓存函数
const User = lazy(() => import("./pages/users/[id].js"));
// 预加载函数function preloadUser({params, location}) { void getUser(params.id)}
// 在路由定义中传入<Route path="/users/:id" component={User} preload={preloadUser} />;
在路由组件内使用
在路由组件内使用:
import { getUser } from ... // 缓存函数
export default function User(props) { const user = createAsync(() => getUser(props.params.id)); return <h1>{user().name}</h1>;}
Query 函数功能
query
实现了以下功能:
- 在服务器端请求生命周期内进行去重。
- 在浏览器中填充预加载缓存 - 持续 5 秒。 当路由在悬停时预加载或进入路由时调用预加载时,它将确保去重调用。
- 基于键的响应式重新获取机制。 这可以防止非新路由在操作重新验证时重新触发。
- 作为浏览器导航的前进/后退缓存,最长可达 5 分钟。 任何用户导航或链接点击都会绕过此缓存。 重新验证或新的获取会更新缓存。
缓存键
为确保缓存键的一致性和唯一性,参数会使用 JSON.stringify
进行确定性序列化。
在序列化之前,对象中的键值对会被排序,这样属性的顺序不会影响序列化。
例如,{ name: 'Ryan', awesome: true }
和 { awesome: true, name: 'Ryan' }
都会序列化为相同的字符串,从而产生相同的缓存键。
返回值
返回值是一个 CachedFunction
,这是一个与你传递给 cache
的函数具有相同签名的函数。
这个缓存函数使用缓存键存储返回值。
在大多数情况下,即使创建的函数被重复调用,这也会暂时阻止传入的函数使用相同的参数运行。
参数
参数 | 类型 | 描述 |
---|---|---|
fn | (...args: any) => any | 你想要缓存其返回值的函数。 |
name * | string | 你想用作缓存键其余部分的任意字符串。 |
*由于内部缓存由所有使用 query
的函数共享,该字符串对于传递给 query
的每个函数都应该是唯一的。
如果多个函数使用相同的键,一个函数可能会返回另一个函数的缓存结果。
方法
.key
和 .keyFor
Query 函数提供了 .key
和 .keyFor
,这在涉及失效的情况下检索使用的键时很有用:
let id = 5;getUser.key; // 返回 "users"getUser.keyFor(id); // 返回 "users[5]"
revalidate
可以使用 revalidate
方法或从操作响应中设置的 revalidate
键来重新验证 query
。
如果传入整个键,它将使该缓存的所有条目失效(例如上例中的 users
)。
如果只需要使单个条目失效,则提供了 keyFor
。
要重新验证缓存中的所有内容,请传入 undefined
作为键。