npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

soon-fetch

v4.0.0

Published

a request lib alternative to axios with timeout, request reusing, race, response cache ...

Downloads

641

Readme

English | 中文 | Installation

soon-fetch

A lightweight http request lib , alternative to axios with timeout, request reusing, race, response cache ...

  • 🌐 automatic parse restful api url parameters
  • ⭐ rapid define a request api
  • ⌛ timeout disconnect
  • 📦 request reusing
  • 🚀 request race
  • 📝 response cache
  • 🔤 automatic serialization of JSON
  • 📏 .min size less than 6K, smaller after zip
  • 💡 smart type tips with Typescript

Example

github: soon-admin-vue3
github: soon-admin-react-nextjs

import { createSoon, soonFetch } from "soon-fetch";

// 使用 soonFetch 作为基础请求函数
const request = async <T>(url: string, options?: SoonOptions) => {
  const isGet = !options?.method || options?.method.toLocaleLowerCase() === "get";
  const response = await soonFetch<T>({
    url,
    options,
    baseURL: '/api',
    baseOptions: {
      timeout: 20 * 1000,
      headers: new Headers({
        Authorization: "Bearer " + localStorage.getItem("token"),
      }),
      share: isGet ? true : false,
      staleTime: isGet ? 2 * 1000 : 0,
    },
  });
  return response;
};

const soon = createSoon(request);

/** GET */
soon.get("/user?id=123");
soon.get("/user", { query: { id: 123 } });
soon.get("/user/:id", { params: { id: 123 } });

/** POST */
soon.post("/login", { body: { username: "admin", password: "123456" } });

/**Define API */
export const login = soon
  .POST("/user/login")
  .Body<{ username: string; password: string }>()
  .Ok<{ token: string }>();
//the develop tools will have type tips for request and response
login({ username: "admin", password: "123" }).then((res) => {
  localStorage.setItem("token", res.token);
});

Features

Shortcut
soon.get(url, options);
soon.post(url, options);
soon.put(url, options);
soon.patch(url, options);
soon.delete(url, options);
soon.head(url, options);
soon.options(url, options);
Restful Url Params

url like /:key , will handle the key

soon.get("/api/user/:id", { params: { id: 1 } });
// api/user/1
soon.get("/api/:job/:year", { params: { job: "engineer", year: 5 } });
//api/engineer/5
Timeout
//** the request level timeout, will override the instance level timeout  */
soon.get(url, { timeout: 1000 * 20 });
Share pending request

If a request is made again before the first completes, will reuse the first request instead of making a new request.

soon.get(url, { share: true });
Response cache

A cached response will be returned if the request is made again within the specified time.

soon.get(url, { staleTime: 1000 * 60 * 5 });
Request race

‌If a second request is made before the first completes, abort the first to avoid race conditions from out-of-order responses.

import { useEffect, useRef, useState } from "react";

type User = { name: string; job: string };
const api = soon.GET("/api/users").Query<{ page: number }>().Ok<User[]>();
export default function App() {
  const refAbort = useRef([]);
  const [list, setList] = useState<User[]>([]);
  const [page, setPage] = useState(1);
  useEffect(() => {
    api({ page }, { aborts: refAbort.current })
      .then(setList)
      .catch(console.log);
  }, [page]);
  return (
    <div>
      <button onClick={() => setPage((pre) => pre + 1)}>next</button>
      <div>
        {list.map((item) => (
          <div key={item.name}>{item.name}</div>
        ))}
      </div>
    </div>
  );
}
Rapid Define APIs
//can be GET POST PATCH PUT DELETE
  soon.GET(url:string).Query<Query>().Ok<Response>()
  soon.POST(url:string).Body<Body>().Ok<Response>()
  soon.GET(url:string).Options({ timeout: 5000 }).Ok<Response>()
  soon.POST(url:string).Body<Body>().Options({ timeout: 5000 }).Ok<Response>()
//define an api
export const getUserInfo = soon.GET("/user/:id").Ok();
//then use in any where
getUserInfo({ id: 2 }).then((res) => console.log(res));
//define an api with options
export const getUserInfoWithOptions = soon.GET("/user/:id").Options({ timeout: 5000 }).Ok();
//then use in any where
getUserInfoWithOptions({ id: 2 }).then((res) => console.log(res));

//with typescript,
export const login = soon
  .POST("/user/login")
  .Body<{ username: string; password: string }>()
  .Ok<{ token: string }>();
//the develop tools will have type tips for request and response
login({ username: "admin", password: "123" }).then((res) => {
  localStorage.setItem("token", res.token);
});

//with Params for type safety
export const getUserById = soon.GET("/user/:id").Params<{ id: number }>().Ok<{ id: number; name: string }>();
getUserById({ id: 1 }).then((res) => console.log(res));

API

SoonOptions

// function fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>
// RequestInit  is fetch's init options
type SoonOptions = Omit<RequestInit, "body"> & {
  body?: RequestInit["body"] | object;
  query?:
    | Record<
        string,
        | string
        | number
        | boolean
        | null
        | undefined
        | (string | number | boolean | null | undefined)[]
      >
    | URLSearchParams;
  params?: Record<string, string | number>;
  timeout?: number;
  aborts?: AbortController[] | never[];
  share?: boolean;
  staleTime?: number;
};

createSoon

Create a soon request instance.

Parameters:

  • request: A function to handle the actual request, receives url and options, returns a Promise

Returns: An object containing request method, API methods (GET, POST, PUT, DELETE, PATCH), and shortcut methods (get, post, put, delete, patch, head, options)

Example:

const soon = createSoon(
  async <T>(url: string, options?: SoonOptions): Promise<T> => {
    const response = await fetch(url, options);
    return response.json();
  }
);

// Usage example
const data = await soon.get<{ id: number; name: string }[]> ("/api/users");

// Define API with options
export const login = soon
  .POST("/user/login")
  .Body<{ username: string; password: string }>()
  .Ok<{ token: string }>();

login({ username: "admin", password: "123" }).then((res) => {
  localStorage.setItem("token", res.token);
});

createShortApi

Factory function to create API shortcut methods. Used to generate type-safe API calling methods, supporting path parameters, query parameters, and request body.

Parameters:

  • wrapper: Wrapper function to handle actual request logic

Returns: An object containing GET, POST, PUT, DELETE, PATCH and other methods, each method supports chain calling

Example:

const API = createShortApi(
  async <T>(url: string, method: string, params: Record<string, string | number> | undefined, query: any, body: any, options: any): Promise<T> => {
    // Handle request logic
    const { url: _url } = parseUrl(url, { params, query });
    const response = await fetch(_url, { ...options, method, body });
    return response.json();
  }
);

// Usage example
const getUser = API.GET("/api/users/:id").Ok<{ id: number; name: string }>();
const userData = await getUser({ id: 1 });

// With Params for type safety
const getUserById = API.GET("/api/users/:id").Params<{ id: number }>().Ok<{ id: number; name: string }>();
const userData = await getUserById({ id: 1 });

createShortMethods

Factory function to create shortcut methods.

Parameters:

  • methods: HTTP methods array
  • wrapper: Wrapper function that receives method name and returns a function to process requests

Returns: Shortcut call object containing specified methods

Example:

const methods = createShortMethods(["get", "post"] as const, (method) => {
  return async <T>(url: string, options?: SoonOptions): Promise<T> => {
    const response = await fetch(url, { ...options, method });
    return response.json();
  };
});
// Usage: methods.get<{ id: number; name: string }[]>('/api/users')

parseOptions

Parse URL options.

Parameters:

  • urlOptions: Object containing url, options, baseURL and baseOptions

Returns: Object containing parsed url, options, is_body_json, and abortController

Example:

const parsed = parseOptions({
  url: "/api/users/:id",
  options: { params: { id: "123" } },
  baseURL: "https://api.example.com",
});
// Returns: { url: 'https://api.example.com/api/users/123', options: {...}, is_body_json: false, abortController: AbortController }

mergeHeaders

Merge multiple Headers objects.

Parameters:

  • headersList: List of Headers objects to merge

Returns: Merged Headers object, later ones will overwrite earlier ones with the same name

Example:

const headers1: HeadersInit = { "Content-Type": "application/json" };
const headers2: HeadersInit = { Authorization: "Bearer token" };
const mergedHeaders = mergeHeaders(headers1, headers2);

mergeSignals

Merge multiple AbortSignal signals.

Parameters:

  • signals: Array of AbortSignals to merge
  • timeout: Optional timeout time (milliseconds)

Returns: Merged AbortSignal, any signal termination will trigger termination

Example:

const controller1 = new AbortController();
const controller2 = new AbortController();
const mergedSignal = mergeSignals(
  [controller1.signal, controller2.signal],
  5000
);

parseUrl

Merge URL and its related parameters. Handle baseURL, path parameters and query parameters to generate complete URL.

Parameters:

  • url: Original URL
  • config: Configuration object, including query parameters, path parameters and base URL

Returns: Processed complete URL

Example:

const { url } = parseUrl("/api/users/:id", {
  params: { id: "123" },
  query: { filter: "active" },
  baseURL: "https://api.example.com",
});
// Returns: 'https://api.example.com/api/users/123?filter=active'

mergeOptions

Merge multiple option objects. Merge request options, including special handling of headers and signals.

Parameters:

  • optionsList: List of option objects to merge

Returns: Merged option object

Example:

const defaultOptions = {
  timeout: 5000,
  headers: { "Content-Type": "application/json" },
};
const requestOptions = {
  method: "POST",
  body: JSON.stringify({ name: "John" }),
};
const mergedOptions = mergeOptions(defaultOptions, requestOptions);

isBodyJson

Determine if the request body is a JSON object. Check if body is a plain object, not special types like FormData or Blob.

Parameters:

  • body: Request body

Returns: Returns true if it is a JSON object, otherwise false

Example:

isBodyJson({ name: "John" }); // true
isBodyJson(new FormData()); // false
isBodyJson("string"); // false

genRequestKey

Generate a unique identification key for the request. Generate a unique key value based on the request's URL, method, headers, body, query parameters, etc., used for caching and request sharing.

Parameters:

  • req: Request object containing url and options

Returns: Unique identification string of the request

Example:

const key = genRequestKey({
  url: "/api/users",
  options: { method: "GET", params: { id: 1 } },
});

createRequestStore

Create request store instance. Provides request caching, sharing, and race condition handling.

Parameters:

  • options: Configuration options
    • maxCacheSize: Maximum cache size (default: 100000)
    • checkInterval: Cache check interval in milliseconds (default: 60000)

Returns: Request store object with the following methods:

  • entry(key): Get entry for specific request key
  • dispose(): Dispose the store and clear intervals
  • get(key): Get request by key
  • set(key, value): Set request by key
  • remove(key): Remove request by key
  • getAll(): Get all requests
  • removeAll(): Remove all requests
  • clearCache(): Clear all cache
  • clearExpiredCache(): Clear expired cache
  • abortAll(): Abort all requests

Example:

const store = createRequestStore({ maxCacheSize: 1000, checkInterval: 30000 });
// Use store in requests

deepSort

Deep sort object keys. Recursively sort the keys of an object to generate a stable object serialization result.

Parameters:

  • obj: Object to sort
  • sortArr: Whether to sort arrays (default: false)

Returns: Object with sorted keys

Example:

const obj = { b: 2, a: 1, c: { z: 3, y: 2 } };
const sorted = deepSort(obj);
// Returns: { a: 1, b: 2, c: { y: 2, z: 3 } }

createSilentRefresh

Create silent refresh instance. Used to handle silent refresh functionality when token expires.

Parameters:

  • refresh_token_fn: Function to refresh token

Returns: Function that accepts success and failure callbacks

Example:

const silentRefresh = createSilentRefresh(async () => {
  // Refresh token logic
  await refreshToken();
});

// Usage example
silentRefresh(
  () => console.log("Refresh successful"),
  () => console.log("Refresh failed")
);

soonFetch

A lightweight fetch wrapper with caching, sharing, and race condition handling.

Parameters:

  • config: Configuration object
    • url: Request URL
    • options: Request options (SoonOptions)
    • baseURL: Base URL
    • baseOptions: Base request options
    • store: Custom request store
    • sortRequestKey: Whether to sort request key

Returns: Promise that resolves to the response

Example:

const data = await soonFetch<User[]>({
  url: "/api/users",
  options: {
    method: "GET",
    query: { page: 1 },
    share: true,
    staleTime: 5000,
  },
  baseURL: "https://api.example.com",
});

toFormData

Convert object to FormData. Used to convert plain objects to FormData format, supports files and regular values.

Parameters:

  • body: Object to convert

Returns: Converted FormData object

Example:

const formData = toFormData({
  name: "John",
  avatar: fileBlob,
  age: 30,
});

progressDownload

Download with progress tracking. Used to download files with progress updates.

Parameters:

  • response: Response object
  • onProgress: Progress callback function

Returns: Promise that resolves to ArrayBuffer

Example:

const response = await fetch("/api/download");
const buffer = await progressDownload(response, (progress, downloaded, total) => {
  console.log(`Progress: ${progress}%, Downloaded: ${downloaded}/${total}`);
});

progressReadBody

Read response body with progress tracking. Used to read response bodies with progress updates.

Parameters:

  • body: ReadableStream
  • onProgress: Progress callback function
  • total: Total size in bytes (default: 0)

Returns: Promise that resolves to ArrayBuffer

Example:

const response = await fetch("/api/download");
const buffer = await progressReadBody(response.body!, (progress, downloaded, total) => {
  console.log(`Progress: ${progress}%, Downloaded: ${downloaded}/${total}`);
});

requestWithStore

Request wrapper with store support. Used to handle requests with caching, sharing, and race condition handling.

Parameters:

  • store: Request store instance
  • requestFn: Request function
  • requestKey: Request key
  • fetchAbort: AbortController
  • options: Options object

Returns: Promise that resolves to the response

Example:

const store = createRequestStore();
const data = await requestWithStore(store, () => fetch(url, options), requestKey, abortController, {
  share: true,
  staleTime: 5000,
});

English | 中文 | Installation

soon-fetch

极轻量的请求库,不到 6K

  • 🌐 自动解析 rest Url 的参数
  • ⭐ 快捷定义请求 api
  • ⌛ 超时断开
  • 📦 请求复用
  • 🚀 请求竞态
  • 📝 响应缓存
  • 🔤 自动处理 JSON
  • 📏 不到 6K , zip 后会更小
  • 💡 用 typescript 有智能类型提醒

示例

github: soon-admin-vue3
github: soon-admin-react-nextjs

import { createSoon, soonFetch } from "soon-fetch";

// 使用 soonFetch 作为基础请求函数
const request = async <T>(url: string, options?: SoonOptions) => {
  const isGet = !options?.method || options?.method.toLocaleLowerCase() === "get";
  const response = await soonFetch<T>({
    url,
    options,
    baseURL: '/api',
    baseOptions: {
      timeout: 20 * 1000,
      headers: new Headers({
        Authorization: "Bearer " + localStorage.getItem("token"),
      }),
      share: isGet ? true : false,
      staleTime: isGet ? 2 * 1000 : 0,
    },
  });
  return response;
};

const soon = createSoon(request);

/** GET */
soon.get("/user?id=123");
soon.get("/user", { query: { id: 123 } });
soon.get("/user/:id", { params: { id: 123 } });

/** POST */
soon.post("/login", { body: { username: "admin", password: "123456" } });

/**定义 API */
export const login = soon
  .POST("/user/login")
  .Body<{ username: string; password: string }>()
  .Ok<{ token: string }>();

//开发工具会有请求和响应的智能提醒
login({ username: "admin", password: "123" }).then((res) => {
  localStorage.setItem("token", res.token);
});

//使用 Params 进行类型安全定义
export const getUserById = soon.GET("/user/:id").Params<{ id: number }>().Ok<{ id: number; name: string }>();
getUserById({ id: 1 }).then((res) => console.log(res));

特别功能

快捷方法
soon.get(url, options);
soon.post(url, options);
soon.put(url, options);
soon.patch(url, options);
soon.delete(url, options);
soon.head(url, options);
soon.options(url, options);
Restful Url 参数自动处理

url 包含 /:key 会解析匹配 key

soon.get("/api/user/:id", { params: { id: 1 } });
// api/user/1
soon.get("/api/:job/:year", { params: { job: "engineer", year: 5 } });
//api/engineer/5
超时
//** 请求级超时, 会覆盖实例级超时  */
soon.get(url, { timeout: 1000 * 20 });
共享未完成的请求

如果在第一个请求完成之前再次发起相同的请求,则会复用第一个请求,而不是发起新的请求。

soon.get(url, { share: true });
响应缓存

如果在指定时间内再次发起相同的请求,则会返回缓存的响应。

soon.get(url, { staleTime: 1000 * 60 * 5 });
请求竞态

如果在第一个请求完成之前发起第二个请求,则会中止第一个请求,以避免因响应顺序错乱导致的问题。

import { useEffect, useRef, useState } from "react";

type User = { name: string; job: string };
const api = soon.GET("/api/users").Query<{ page: number }>().Ok<User[]>();
export default function App() {
  const refAbort = useRef([]);
  const [list, setList] = useState<User[]>([]);
  const [page, setPage] = useState(1);
  useEffect(() => {
    api({ page }, { aborts: refAbort.current })
      .then(setList)
      .catch(console.log);
  }, [page]);
  return (
    <div>
      <button onClick={() => setPage((pre) => pre + 1)}>next</button>
      <div>
        {list.map((item) => (
          <div key={item.name}>{item.name}</div>
        ))}
      </div>
    </div>
  );
}
快速定义 API
  //可以是 GET POST PATCH PUT DELETE
  //GET 请求数据传递至query,其他方法请求数据传递至body
  soon.GET(url:string).Query<Query>().Ok<Response>()
  soon.POST(url:string).Body<Body>().Ok<Response>()
  soon.GET(url:string).Options({ timeout: 5000 }).Ok<Response>()
  soon.POST(url:string).Body<Body>().Options({ timeout: 5000 }).Ok<Response>()

  //定义一个api
 export const getUserInfo=soon.GET('/user/:id').Ok()
  //使用
  getUserInfo({id:2}).then(res=>console.log(res))
  //定义一个带选项的api
 export const getUserInfoWithOptions=soon.GET('/user/:id').Options({ timeout: 5000 }).Ok()
  //使用
  getUserInfoWithOptions({id:2}).then(res=>console.log(res))

  //用typescript,
 export const login=soon
  .POST('/user/login')
  .Body<{username:string,password:string}>()
  .Ok<{token:string}>()
 //开发工具会有请求和响应的智能提醒
  login({username:'admin',password:'123'}).then(res=>{
    localStorage.setItem('token', res.token);
  })

  //使用 Params 进行类型安全定义
  export const getUserById = soon.GET('/user/:id').Params<{ id: number }>().Ok<{ id: number; name: string }>();
  getUserById({ id: 1 }).then(res => console.log(res));

API

SoonOptions

// function fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>
// RequestInit  为原生 fetch 的 init 选项
type SoonOptions = Omit<RequestInit, "body"> & {
  body?: RequestInit["body"] | object;
  query?:
    | Record<
        string,
        | string
        | number
        | boolean
        | null
        | undefined
        | (string | number | boolean | null | undefined)[]
      >
    | URLSearchParams;
  params?: Record<string, string | number>;
  timeout?: number;
  aborts?: AbortController[] | never[];
  share?: boolean;
  staleTime?: number;
};

createSoon

创建一个 soon 请求实例。

参数:

  • request: 用于处理实际请求的函数,接收 url 和 options,返回一个 Promise

返回: 包含 request 方法、API 方法(GET、POST、PUT、DELETE、PATCH)和快捷方法(get、post、put、delete、patch、head、options)的对象

示例:

const soon = createSoon(
  async (url, options) => {
    const response = await fetch(url, options);
    return response.json();
  }
);

// 使用示例
const data = await soon.get("/api/users");

// 定义带选项的 API
export const login = soon
  .POST("/user/login")
  .Body<{ username: string; password: string }>()
  .Ok<{ token: string }>();

login({ username: "admin", password: "123" }).then((res) => {
  localStorage.setItem("token", res.token);
});

createShortApi

创建 API 快捷方法的工厂函数。 用于生成类型安全的 API 调用方法,支持路径参数、查询参数和请求体。

参数:

  • wrapper: 包装函数,用于处理实际的请求逻辑

返回: 包含 GET、POST、PUT、DELETE、PATCH 等方法的对象,每个方法都支持链式调用

示例:

const API = createShortApi(
  async (url, method, params, query, body, options) => {
    // 处理请求逻辑
    const { url: _url } = parseUrl(url, { params, query });
    const response = await fetch(_url, { ...options, method, body });
    return response.json();
  }
);

// 使用示例
const getUser = API.GET("/api/users/:id").Ok();
const userData = await getUser({ id: 1 });

// 使用 Params 进行类型安全定义
const getUserById = API.GET("/api/users/:id").Params<{ id: number }>().Ok<{ id: number; name: string }>();
const userData = await getUserById({ id: 1 });

createShortMethods

创建快捷方法的工厂函数。

参数:

  • methods: HTTP 方法数组
  • wrapper: 包装函数,接收方法名,返回处理请求的函数

返回: 包含指定方法的快捷调用对象

示例:

const methods = createShortMethods(["get", "post"] as const, (method) => {
  return (url, options) => fetch(url, { ...options, method });
});
// 使用: methods.get('/api/users')

parseOptions

解析 URL 选项。

参数:

  • urlOptions: 包含 url、options、baseURL 和 baseOptions 的对象

返回: 包含解析后的 url、options、is_body_json 和 abortController 的对象

示例:

const parsed = parseOptions({
  url: "/api/users/:id",
  options: { params: { id: "123" } },
  baseURL: "https://api.example.com",
});
// 返回: { url: 'https://api.example.com/api/users/123', options: {...}, is_body_json: false, abortController: AbortController }

mergeHeaders

合并多个 Headers 对象。

参数:

  • headersList: 要合并的 Headers 对象列表

返回: 合并后的 Headers 对象,后面的会覆盖前面的同名 header

示例:

const headers1: HeadersInit = { "Content-Type": "application/json" };
const headers2: HeadersInit = { Authorization: "Bearer token" };
const mergedHeaders = mergeHeaders(headers1, headers2);

mergeSignals

合并多个 AbortSignal 信号。

参数:

  • signals: 要合并的 AbortSignal 数组
  • timeout: 可选的超时时间(毫秒)

返回: 合并后的 AbortSignal,任意一个信号终止都会触发终止

示例:

const controller1 = new AbortController();
const controller2 = new AbortController();
const mergedSignal = mergeSignals(
  [controller1.signal, controller2.signal],
  5000
);

parseUrl

合并 URL 及其相关参数。 处理 baseURL、路径参数和查询参数,生成完整 URL。

参数:

  • url: 原始 URL
  • config: 配置对象,包含查询参数、路径参数和基础 URL

返回: 处理后的完整 URL

示例:

const url = parseUrl("/api/users/:id", {
  params: { id: "123" },
  query: { filter: "active" },
  baseURL: "https://api.example.com",
});
// 返回: 'https://api.example.com/api/users/123?filter=active'

mergeOptions

合并多个选项对象。 合并请求选项,包括 headers 和 signal 等特殊处理。

参数:

  • optionsList: 要合并的选项对象列表

返回: 合并后的选项对象

示例:

const defaultOptions = {
  timeout: 5000,
  headers: { "Content-Type": "application/json" },
};
const requestOptions = {
  method: "POST",
  body: JSON.stringify({ name: "John" }),
};
const mergedOptions = mergeOptions(defaultOptions, requestOptions);

isBodyJson

判断请求体是否为 JSON 对象。 检查 body 是否为普通对象,而不是 FormData、Blob 等特殊类型。

参数:

  • body: 请求体

返回: 如果是 JSON 对象返回 true,否则返回 false

示例:

isBodyJson({ name: "John" }); // true
isBodyJson(new FormData()); // false
isBodyJson("string"); // false

genRequestKey

生成请求的唯一标识键。 根据请求的 URL、方法、headers、body、查询参数等生成唯一键值,用于缓存和请求共享。

参数:

  • req: 包含 url 和 options 的请求对象

返回: 请求的唯一标识字符串

示例:

const key = genRequestKey({
  url: "/api/users",
  options: { method: "GET", params: { id: 1 } },
});

createRequestStore

创建请求存储实例。 提供请求缓存、共享和竞态条件处理。

参数:

  • options: 配置选项
    • maxCacheSize: 最大缓存大小(默认: 100000)
    • checkInterval: 缓存检查间隔(毫秒,默认: 60000)

返回: 请求存储对象,包含以下方法:

  • entry(key): 获取特定请求键的条目
  • dispose(): 销毁存储并清除定时器
  • get(key): 根据键获取请求
  • set(key, value): 根据键设置请求
  • remove(key): 根据键移除请求
  • getAll(): 获取所有请求
  • removeAll(): 移除所有请求
  • clearCache(): 清除所有缓存
  • clearExpiredCache(): 清除过期缓存
  • abortAll(): 中止所有请求

示例:

const store = createRequestStore({ maxCacheSize: 1000, checkInterval: 30000 });
// 在请求中使用 store

deepSort

深度排序对象键。 递归地对对象的键进行排序,用于生成稳定的对象序列化结果。

参数:

  • obj: 要排序的对象
  • sortArr: 是否对数组进行排序(默认: false)

返回: 键排序后的对象

示例:

const obj = { b: 2, a: 1, c: { z: 3, y: 2 } };
const sorted = deepSort(obj);
// 返回: { a: 1, b: 2, c: { y: 2, z: 3 } }

createSilentRefresh

创建静默刷新实例。 用于处理 token 过期时的静默刷新功能。

参数:

  • refresh_token_fn: 刷新 token 的函数

返回: 接收成功和失败回调的函数

示例:

const silentRefresh = createSilentRefresh(async () => {
  // 刷新token逻辑
  await refreshToken();
});

// 使用示例
silentRefresh(
  () => console.log("刷新成功"),
  () => console.log("刷新失败")
);

soonFetch

一个轻量级的 fetch 包装器,支持缓存、共享和竞态条件处理。

参数:

  • config: 配置对象
    • url: 请求 URL
    • options: 请求选项 (SoonOptions)
    • baseURL: 基础 URL
    • baseOptions: 基础请求选项
    • store: 自定义请求存储
    • sortRequestKey: 是否对请求键进行排序

返回: 解析为响应的 Promise

示例:

const data = await soonFetch<User[]>({
  url: "/api/users",
  options: {
    method: "GET",
    query: { page: 1 },
    share: true,
    staleTime: 5000,
  },
  baseURL: "https://api.example.com",
});

toFormData

将对象转换为 FormData。 用于将普通对象转换为 FormData 格式,支持文件和普通值。

参数:

  • body: 要转换的对象

返回: 转换后的 FormData 对象

示例:

const formData = toFormData({
  name: "John",
  avatar: fileBlob,
  age: 30,
});

progressDownload

带进度的下载。 用于下载文件并跟踪进度。

参数:

  • response: 响应对象
  • onProgress: 进度回调函数

返回: 解析为 ArrayBuffer 的 Promise

示例:

const response = await fetch("/api/download");
const buffer = await progressDownload(response, (progress, downloaded, total) => {
  console.log(`进度: ${progress}%, 已下载: ${downloaded}/${total}`);
});

progressReadBody

带进度的读取响应体。 用于读取响应体并跟踪进度。

参数:

  • body: ReadableStream
  • onProgress: 进度回调函数
  • total: 总大小(字节,默认: 0)

返回: 解析为 ArrayBuffer 的 Promise

示例:

const response = await fetch("/api/download");
const buffer = await progressReadBody(response.body, (progress, downloaded, total) => {
  console.log(`进度: ${progress}%, 已下载: ${downloaded}/${total}`);
});

requestWithStore

带存储支持的请求包装器。 用于处理带有缓存、共享和竞态条件处理的请求。

参数:

  • store: 请求存储实例
  • requestFn: 请求函数
  • requestKey: 请求键
  • fetchAbort: AbortController
  • options: 选项对象

返回: 解析为响应的 Promise

示例:

const store = createRequestStore();
const data = await requestWithStore(store, () => fetch(url, options), requestKey, abortController, {
  share: true,
  staleTime: 5000,
});

English | 中文 | Installation

安装 Installation
    npm install soon-fetch