onRequestError(ctx.error)rejectonRequestError 收到原始 error,可以在 reject 前替换 ctx.error。
Hooks 用来复用公共请求和响应行为,不会把 HTTP 客户端绑定到路由、UI 组件库或状态库。
onRequest修改标准化前的 requestadapter执行 transportonResponse修改解析后的 responsepolicy执行项目 response policyonRequestError(ctx.error)→rejectonRequestError 收到原始 error,可以在 reject 前替换 ctx.error。
kind: ok→onSuccess(ctx.value)→resolvekind: non-ok→onResponseError(ctx.error)→rejectnon-ok 生成分类后的 error,onResponseError 可以在 reject 前替换 ctx.error。
resolve | reject→onFinally(ctx)→settle PromiseonFinally 在 resolve 和 reject 路径都执行。请求和 cleanup 同时失败时返回 AggregateError。
onRequestError 处理 adapter 抛错。onResponseError 在 response policy 分类为 non-ok 后执行。onSuccess 收到即将 resolve 的值。onFinally 在所有路径执行一次。
hooks 按顺序执行,返回值会被忽略。需要定制时修改当前阶段对应的 ctx.request、ctx.response、ctx.error 或 ctx.value。
const http = createHttp({
adapter: "fetch",
hooks: {
onRequest: [auth(getToken), addLocale, addTraceId],
onRequestError: reportNetworkFailure,
onResponse: normalizeSharedHeaders,
onResponseError: [handleUnauthorized, showErrorToast],
onSuccess: observeResolvedValue,
onFinally: stopTrace,
},
});const http = createHttp({
adapter: "fetch",
hooks: {
onSuccess: (ctx) => {
ctx.value = normalizeResolvedValue(ctx.value);
},
onFinally: (ctx) => {
finishTrace(ctx.request, ctx.error);
},
},
});前一个 cleanup hook 失败后,后面的 onFinally 仍会执行。请求和 cleanup 同时失败时,Promise reject AggregateError:第一个元素是请求 error,后面按声明顺序排列 cleanup errors。
ignoreResponseError: true 只取消 reject,不会清除分类结果。调用方拿到 response body 时,onResponseError、onSuccess 和 onFinally 仍能读取分类后的 ctx.error。
单个接口的例外放在请求参数里,避免全局 hook 根据 URL 分支。
await http.get("/legacy/report", {
hooks: {
onRequest: (ctx) => {
ctx.request.headers["X-Format"] = "legacy";
},
onResponse: (ctx) => {
ctx.response.body = normalizeLegacyReport(ctx.response.body);
},
},
});执行顺序是全局 hooks 在前,单请求 hooks 在后。
import { auth, createHttp } from "@envoijs/http";
const http = createHttp({
adapter: "fetch",
hooks: {
onRequest: auth(() => localStorage.getItem("token")),
},
});请求已经带有 Authorization 时,helper 不会覆盖。
silent 会写入 request metadata。HTTP 和 envelope 失败完成分类后,公共错误 hook 可以直接读取 ctx.error。
import { BizError } from "@envoijs/http";
const http = createHttp({
adapter: "fetch",
hooks: {
onResponseError: (ctx) => {
if (ctx.error instanceof BizError && ctx.request.meta.silent !== true)
showError(ctx.error.msg);
},
},
});
await http.get("/background-check", { silent: true });hook 执行后会抛出同一个 error,store 和 query library 能收到失败状态。
需要把多个阶段封装成一个模块时,参考可复用 Middleware。
hook 的返回值不会替换失败请求。Token refresh 需要外层 request wrapper 或 adapter 能力。用一个共享 refresh promise 和一次重试标记,避免并发刷新和无限递归。