文档中心

探索 DWeb 框架的无限可能,构建下一代高性能 Web 应用

HTTP 请求库

提供基于 fetch 的前端 HTTP 请求库,支持拦截器、错误处理、请求取消、重试、并发请求、文件上传/下载、进度追踪等功能。所有函数在服务端和客户端都可用,部分功能如文件上传/下载、进度追踪在服务端环境可能受限。

快速开始

Code
import { http, get, post } from "@dreamer/dweb/utils/http";

// 使用默认实例
const data = await http.get("/api/users");
const result = await http.post("/api/users", { name: "Alice" });

// 使用便捷方法
const users = await get("/api/users");
const newUser = await post("/api/users", { name: "Bob" });

创建自定义实例

Code
import { createHttpClient } from "@dreamer/dweb/utils/http";

const api = createHttpClient({
  baseURL: "https://api.example.com",
  headers: {
    Authorization: "Bearer token",
  },
  timeout: 5000, // 5秒超时
});

// 使用自定义实例
const data = await api.get("/users");

请求拦截器

Code
import { http } from "@dreamer/dweb/utils/http";

// 请求拦截器:添加 token
http.interceptors.request.use((config) => {
  const token = globalThis.localStorage?.getItem("token");
  if (token) {
    config.headers = {
      ...config.headers,
      Authorization: `Bearer ${token}`,
    };
  }
  return config;
});

响应拦截器

Code
import { http } from "@dreamer/dweb/utils/http";

// 响应拦截器:统一处理错误
http.interceptors.response.use(
  (response) => {
    // 成功响应,直接返回
    return response;
  },
  async (error) => {
    // 错误处理
    if (error.response?.status === 401) {
      // token 过期,跳转登录
      globalThis.location.href = "/login";
    }
    throw error;
  },
);

完整示例

Code
import { createHttpClient } from "@dreamer/dweb/utils/http";

// 创建 API 客户端
const api = createHttpClient({
  baseURL: "/api",
  timeout: 10000,
});

// 请求拦截器:自动添加 token
api.interceptors.request.use((config) => {
  const token = globalThis.localStorage?.getItem("token");
  if (token) {
    config.headers = {
      ...config.headers,
      Authorization: `Bearer ${token}`,
    };
  }
  return config;
});

// 响应拦截器:统一处理响应
api.interceptors.response.use(
  (response) => response,
  async (error) => {
    if (error.response?.status === 401) {
      // 未授权,清除 token 并跳转登录
      globalThis.localStorage?.removeItem("token");
      globalThis.location.href = "/login";
    }
    return Promise.reject(error);
  },
);

// 使用
const users = await api.get("/users", {
  params: { page: 1, limit: 10 },
});

const newUser = await api.post("/users", {
  name: "Alice",
  email: "[email protected]",
});

取消请求

Code
import { http } from "@dreamer/dweb/utils/http";

const controller = new AbortController();

// 发送请求
const promise = http.get("/api/data", {
  signal: controller.signal,
});

// 取消请求
controller.abort();

超时设置

Code
// 全局超时(创建实例时设置)
const api = createHttpClient({ timeout: 5000 });

// 单次请求超时
await api.get("/api/data", { timeout: 3000 });

请求重试

Code
import { http } from "@dreamer/dweb/utils/http";

// 配置重试
await http.get("/api/data", {
  retry: {
    times: 3,           // 重试次数
    delay: 1000,        // 重试延迟(毫秒)
    retryCondition: (error) => {
      // 自定义重试条件
      return error instanceof Response && error.status >= 500;
    },
    onRetry: (error, attempt) => {
      console.log(`重试第 ${attempt} 次`);
    },
  },
});

并发请求

Code
import { http, all, allSettled } from "@dreamer/dweb/utils/http";

// 并发请求所有接口(类似 Promise.all)
const [users, posts, comments] = await http.all([
  http.get("/api/users"),
  http.get("/api/posts"),
  http.get("/api/comments"),
]);

// 并发请求(部分失败也返回结果,类似 Promise.allSettled)
const results = await http.allSettled([
  http.get("/api/users"),
  http.get("/api/posts"),
  http.get("/api/comments"),
]);

// 使用便捷方法
const data = await all([
  http.get("/api/users"),
  http.get("/api/posts"),
]);

请求去重

Code
import { http } from "@dreamer/dweb/utils/http";

// 启用请求去重(防止重复请求)
await http.get("/api/users", {
  dedupe: true,        // 启用去重
  dedupeKey: "users", // 自定义去重键(可选)
});

// 如果同时发起多个相同请求,只会发送一次
Promise.all([
  http.get("/api/users", { dedupe: true }),
  http.get("/api/users", { dedupe: true }),
  http.get("/api/users", { dedupe: true }),
]); // 只会发送一次请求

文件上传

Code
import { http, upload } from "@dreamer/dweb/utils/http";

// 上传文件
const file = document.querySelector('input[type="file"]')?.files?.[0];
if (file) {
  const result = await http.upload("/api/upload", file, {
    onUploadProgress: (progress) => {
      console.log(`上传进度: ${progress.percent}%`);
    },
  });
}

// 使用便捷方法
await upload("/api/upload", file);

文件下载

Code
import { http, download, downloadFile } from "@dreamer/dweb/utils/http";

// 下载文件(返回 Blob)
const blob = await http.download("/api/files/report.pdf", {
  onDownloadProgress: (progress) => {
    console.log(`下载进度: ${progress.percent}%`);
  },
});

// 下载文件并保存到本地(浏览器环境)
await http.downloadFile("/api/files/report.pdf", "report.pdf");

// 使用便捷方法
await downloadFile("/api/files/report.pdf", "report.pdf");

请求进度追踪

Code
import { http } from "@dreamer/dweb/utils/http";

// 上传进度
await http.post("/api/upload", formData, {
  onUploadProgress: (progress) => {
    console.log(`上传: ${progress.loaded}/${progress.total}`);
    console.log(`进度: ${progress.percent}%`);
  },
});

// 下载进度
await http.get("/api/files/data.zip", {
  responseType: "blob",
  onDownloadProgress: (progress) => {
    console.log(`下载: ${progress.loaded}/${progress.total}`);
    console.log(`进度: ${progress.percent}%`);
  },
});

响应类型

HTTP 客户端支持多种响应类型:

Code
import { http } from "@dreamer/dweb/utils/http";

// JSON 响应(默认)
const jsonData = await http.get("/api/users", {
  responseType: "json",
});

// 文本响应
const textData = await http.get("/api/text", {
  responseType: "text",
});

// Blob 响应(用于文件)
const blobData = await http.get("/api/file", {
  responseType: "blob",
});

// ArrayBuffer 响应
const bufferData = await http.get("/api/binary", {
  responseType: "arrayBuffer",
});

// FormData 响应
const formData = await http.get("/api/form", {
  responseType: "formData",
});

请求配置选项

Code
import { http } from "@dreamer/dweb/utils/http";

await http.get("/api/data", {
  // 请求头
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer token",
  },

  // URL 查询参数
  params: {
    page: 1,
    limit: 10,
    keyword: "search",
  },

  // 超时时间(毫秒)
  timeout: 5000,

  // 是否携带凭证(cookies)
  credentials: "include",

  // 请求模式
  mode: "cors", // "cors" | "no-cors" | "same-origin"

  // 缓存模式
  cache: "default", // "default" | "no-store" | "reload" | "no-cache" | "force-cache" | "only-if-cached"

  // 重定向模式
  redirect: "follow", // "follow" | "error" | "manual"

  // 响应类型
  responseType: "json", // "json" | "text" | "blob" | "arrayBuffer" | "formData"
});

API 参考

Code
// HttpClient 类

// 构造函数
const client = new HttpClient({
  baseURL?: string;        // 基础 URL
  headers?: Record<string, string>;  // 默认请求头
  timeout?: number;        // 默认超时时间(毫秒)
});

// 基础 HTTP 方法
- get<T>(url, config?) - GET 请求
- post<T>(url, data?, config?) - POST 请求
- put<T>(url, data?, config?) - PUT 请求
- delete<T>(url, config?) - DELETE 请求
- patch<T>(url, data?, config?) - PATCH 请求
- head<T>(url, config?) - HEAD 请求
- options<T>(url, config?) - OPTIONS 请求
- request<T>(config) - 通用请求方法

// 并发请求
- all<T>(requests) - 并发请求(类似 Promise.all)
- allSettled<T>(requests) - 并发请求(类似 Promise.allSettled)

// 文件操作
- upload<T>(url, file, config?) - 文件上传
- download(url, config?) - 文件下载(返回 Blob)
- downloadFile(url, filename?, config?) - 下载文件并保存到本地

// 拦截器
- interceptors.request.use(interceptor) - 添加请求拦截器
- interceptors.response.use(onFulfilled, onRejected?) - 添加响应拦截器

// 便捷函数
- get<T>(url, config?) - GET 请求
- post<T>(url, data?, config?) - POST 请求
- put<T>(url, data?, config?) - PUT 请求
- del<T>(url, config?) - DELETE 请求
- patch<T>(url, data?, config?) - PATCH 请求
- head<T>(url, config?) - HEAD 请求
- options<T>(url, config?) - OPTIONS 请求
- request<T>(config) - 通用请求方法
- all<T>(requests) - 并发请求
- allSettled<T>(requests) - 并发请求
- upload<T>(url, file, config?) - 文件上传
- download(url, config?) - 文件下载
- downloadFile(url, filename?, config?) - 下载文件并保存
- createHttpClient(config?) - 创建 HTTP 客户端实例

// 默认实例
import { http } from "@dreamer/dweb/utils/http";
// http 是默认的 HttpClient 实例,可以直接使用