Promise 与查询状态
其他系统负责执行时使用 usePromiseState;用户触发异步操作时使用 useExecutePromise;查询对象驱动操作时使用 useQuery。每个已挂载 Hook 只维护最新的一份结果,不提供共享缓存或自动重试。
状态与执行
| API / 选项 | 契约 |
|---|---|
usePromiseState<R,E>(options?) | 初始状态为 initialStatus ?? PromiseStatus.IDLE,结果和错误均为 undefined;返回状态和设置函数。 |
setLoading() | 清除错误,保留上次结果。 |
setSuccess(result) / setError(error) | 设置成功结果,或设置错误并清空结果;随后等待对应回调。回调失败仅记录日志,不替换状态。 |
setIdle() / 执行器 reset() | 清除结果和错误;单独 reset() 不会取消或作废在途执行。 |
execute(supplier) | 调用 supplier(AbortController),返回 Promise<void>;通过 result 读取数据。新执行取消旧控制器并作废旧结果。 |
propagateError | 默认 false,操作失败进入错误状态;true 时 execute promise 也拒绝。AbortError 被吞掉并恢复 idle。 |
abort() | 作废请求、清空状态、发出取消信号并调用 onAbort;回调失败仅记录日志。 |
supplier 必须把 signal 传给 I/O 才能停止实际工作;即使忽略取消,Hook 仍可丢弃过期结果。卸载清理会取消当前执行。不要在卸载后调用保留的执行器:实现阻止状态提交,但并不保证 supplier 不会运行。
查询所有权
useQuery<Q,R,E> 增加 initialQuery、query、attributes、autoExecute、getQuery()、setQuery(Q);执行器接收 (query, attributes, abortController)。autoExecute 默认为 true。初始化时 query 和 initialQuery 均为 undefined 才没有查询可执行;isValidateQuery 只检查 query !== undefined,不进行 schema 校验。query 覆盖初始化;内容深相等而仅引用变化不会重新查询,执行配置变化则可能触发。initialQuery 只用于初始化,不是响应式替换参数。
将已定义的 query 属性改为 undefined 不会清空保存的查询,还可能再次自动执行旧值。暂停自动执行应设置 autoExecute: false,但这不会取消已经运行的操作;需要作废并取消当前执行时,另外调用 abort()。
setQuery 更新 ref,启用自动执行时立即执行;它本身不是 React 状态通知,也不会去重显式 setter 调用。autoExecute: false 时可先 setQuery 再 execute()。自动执行不会等待调用者 catch,因此无人等待的请求应通过错误状态/onError 处理,而不要设 propagateError: true。useQueryState 只提供查询 ref 行为,不负责取消;应保持其 execute 回调稳定。
选择状态、执行与查询所有权
| 决策 | 纯状态 Hook | 执行器 | 查询 Hook |
|---|---|---|---|
| 谁启动工作? | usePromiseState 外的应用代码 | 调用 execute(supplier) | 默认挂载/查询变化,或显式 execute() |
| 谁保存输入? | 应用代码 | 当前 supplier/调用 | 查询 ref,通过 getQuery() 读取 |
| 谁取消并拒绝旧结果? | 应用代码 | useExecutePromise | 底层执行器 |
| reset 做什么? | 置 idle 并清空 result/error | 相同;运行中的 supplier 之后仍可能置 success | 相同;保留 query |
搜索框文本若需独立于请求状态渲染,应保存在 React state 中;setQuery 本身只是更新 ref。initialQuery 初始化 ref,有定义的响应式 query 优先。查询有效性检查仅排除 undefined,不能作为表单/结构验证器。查询 ref 和异步结果是两个值;改变前者不会立即生成后者。
添加定时器前参见防抖取消;HTTP 示例展示向 Fetcher 传递取消的完整操作。
完整示例
import { useQuery } from '@ahoo-wang/fetcher-react';
export function Search() {
const query = useQuery<{ term: string }, string, Error>({
initialQuery: { term: '' },
execute: async ({ term }, _attributes, controller) => {
const response = await fetch(
`/api/search?q=${encodeURIComponent(term)}`,
{
signal: controller?.signal,
},
);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.text();
},
});
return (
<section>
<input
aria-label="Search"
onChange={e => query.setQuery({ term: e.target.value })}
/>
<button onClick={query.abort}>Cancel</button>
<p role="status">{query.loading ? 'Loading' : query.result}</p>
{query.error && <p role="alert">{query.error.message}</p>}
</section>
);
}示例中的服务 URL 需要应用实现;类型检查不代表已经访问外部服务。
公开签名与类型
以下签名按当前根入口可达声明核对。? 表示可省略;泛型/接口只约束编译期,继承项与关联类型可从 符号索引 定位。运行时默认值和失败行为以本页上文为准。
不拥有执行的状态
usePromiseState
export function usePromiseState<R = unknown, E = FetcherError>(
options?: UsePromiseStateOptions<R, E>,
): UsePromiseStateReturn<R, E>;packages/react/src/core/usePromiseState.ts:119
PromiseStatus
export enum PromiseStatus {
IDLE = 'idle',
LOADING = 'loading',
SUCCESS = 'success',
ERROR = 'error',
}packages/react/src/core/usePromiseState.ts:22
PromiseState
export interface PromiseState<R, E = unknown> {
status: PromiseStatus;
loading: boolean;
result: R | undefined;
error: E | undefined;
}packages/react/src/core/usePromiseState.ts:29
PromiseStateCallbacks
export interface PromiseStateCallbacks<R, E = unknown> {
onSuccess?: (result: R) => void | Promise<void>;
onError?: (error: E) => void | Promise<void>;
}packages/react/src/core/usePromiseState.ts:40
UsePromiseStateOptions
export interface UsePromiseStateOptions<
R,
E = FetcherError,
> extends PromiseStateCallbacks<R, E> {
initialStatus?: PromiseStatus;
}packages/react/src/core/usePromiseState.ts:63
UsePromiseStateReturn
export interface UsePromiseStateReturn<
R,
E = FetcherError,
> extends PromiseState<R, E> {
setLoading: () => void;
setSuccess: (result: R) => Promise<void>;
setError: (error: E) => Promise<void>;
setIdle: () => void;
}packages/react/src/core/usePromiseState.ts:75
显式执行
useExecutePromise
export function useExecutePromise<R = unknown, E = FetcherError>(
options?: UseExecutePromiseOptions<R, E>,
): UseExecutePromiseReturn<R, E>;packages/react/src/core/useExecutePromise.ts:210
UseExecutePromiseOptions
export interface UseExecutePromiseOptions<
R,
E = FetcherError,
> extends UsePromiseStateOptions<R, E> {
propagateError?: boolean;
onAbort?: () => void | Promise<void>;
}packages/react/src/core/useExecutePromise.ts:27
PromiseSupplier
export type PromiseSupplier<R> = (
abortController: AbortController,
) => Promise<R>;packages/react/src/core/useExecutePromise.ts:51
UseExecutePromiseReturn
export interface UseExecutePromiseReturn<
R,
E = FetcherError,
> extends PromiseState<R, E> {
execute: (input: PromiseSupplier<R>) => Promise<void>;
reset: () => void;
abort: () => void;
}packages/react/src/core/useExecutePromise.ts:61
查询驱动执行
useQuery
export function useQuery<Q, R, E = FetcherError>(
options: UseQueryOptions<Q, R, E>,
): UseQueryReturn<Q, R, E>;packages/react/src/core/useQuery.ts:105
QueryOptions
export interface QueryOptions<Q> {
initialQuery?: Q;
query?: Q;
}packages/react/src/core/useQueryState.ts:18
UseQueryOptions
export interface UseQueryOptions<Q, R, E = FetcherError>
extends
UseExecutePromiseOptions<R, E>,
QueryOptions<Q>,
AttributesCapable,
AutoExecuteCapable {
execute: (
query: Q,
attributes?: Record<string, any>,
abortController?: AbortController,
) => Promise<R>;
}packages/react/src/core/useQuery.ts:33
UseQueryReturn
export interface UseQueryReturn<Q, R, E = FetcherError>
extends UseExecutePromiseReturn<R, E>, UseQueryStateReturn<Q> {
execute: () => Promise<void>;
}packages/react/src/core/useQuery.ts:53
不拥有取消的查询 ref
useQueryState
export function useQueryState<Q>(
options: UseQueryStateOptions<Q>,
): UseQueryStateReturn<Q>;packages/react/src/core/useQueryState.ts:113
isValidateQuery
export function isValidateQuery<Q>(query: Q | undefined): query is Q;packages/react/src/core/useQueryState.ts:195
UseQueryStateOptions
export interface UseQueryStateOptions<Q>
extends QueryOptions<Q>, AutoExecuteCapable {
execute: (query: Q) => Promise<void>;
}packages/react/src/core/useQueryState.ts:29
UseQueryStateReturn
export interface UseQueryStateReturn<Q> {
getQuery: () => Q | undefined;
setQuery: (query: Q) => void;
}packages/react/src/core/useQueryState.ts:39
相关专题
Fetcher 请求 Hook · API Hook 工厂 · 防抖执行 · 存储与事件订阅 · 安全 Hook 与路由守卫 · Wow 查询 Hook · 监控、ref 与全屏
