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

@hudc/ajax

v1.0.0

Published

浏览器端的 Ajax 库,支持 TS,拦截器,批量取消,对象字符串化等

Readme

ajax

Build Coverage Version License Types

浏览器端的 Ajax 库,支持 Promise,拦截器,批量取消,对象字符串化

安装

npm install @hudc/ajax

引入

import ajax, {
  defaults,
  interceptor,
  request,
  cancel,
  stringify
} from '@hudc/ajax'

发起请求

function ajax(config: AjaxOptions | string): Promise<any>

示例

// get
ajax('/get')
  .then(res => cosnole.log(res))
  .catch(err => console.log(err.message))
// get
ajax({ url: '/get', method: 'get' })
// post
ajax({ url: '/post', method: 'post' })
// put
ajax({ url: '/put', method: 'put' })
// patch
ajax({ url: '/patch', method: 'patch' })
// delete
ajax({ url: '/del', method: 'delete' })
// head
ajax({ url: '/head', method: 'head' })
// options
ajax({ url: '/options', method: 'options' })

config 配置参数

interface AjaxOptions {
  /** 请求路径 */
  url: string
  /** 请求方法,默认 'get' */
  method?: 'get' | 'post' | 'put' | 'delete' | 'head' | 'options' | 'patch'
  /** 基础路径,默认 '' */
  baseURL?: string
  /** 路径参数,默认 '' (/api/:params/) */
  params?: string
  /** 查询参数,默认 '' (/api?query) */
  query?: Record<string, any> | string
  /** 请求主体,默认 null */
  body?: Record<string, any> | BodyInit | null
  /** 请求头,默认 {}
   * {
   *   common: {
   *     'X-Custom-Header': '优先级最低的通用配置'
   *   },
   *   get: {
   *     'X-Custom-Header': 'get 方法的专属配置'
   *   },
   *   post: {
   *     'X-Custom-Header': 'post 方法的专属配置'
   *   },
   *   ... // 其他方法的专属配置
   *   'X-Custom-Header': '优先级最高的配置方式'
   * }
   */
  headers?: XHRConfigHeaders
  /** 超时的时长,单位秒,默认 0 (没有超时) */
  timeout?: number
  /** 响应数据的类型,默认 'json' */
  responseType?: '' | 'arraybuffer' | 'blob' | 'document' | 'json' | 'text'
  /** 跨站点请求时是否携带凭证,默认 false */
  withCredentials?: boolean
  /** 取消请求的信号,如果没有特别指定,则代表所有激活中的请求,默认 '' */
  signal?: string
  /** 查询参数的格式化方法 */
  transformQuery?: TransformQueryCallBack
  /** 请求主体的格式化方法 */
  transformBody?: TransformBodyCallBack
  /** 响应数据的格式化方法 */
  transformResponse?: TransformResponseCallBack
  /** 定义成功响应的状态码范围,默认 [200, 300) */
  validateStatus?: ValidateStatusCallBack
  /** 下载进度的回调,默认 null */
  onDownloadProgress?: ProgressCallBack | null
  /** 上传进度的回调,默认 null */
  onUploadProgress?: ProgressCallBack | null
}

响应参数

interface XHRResponse {
  /** 响应主体 */
  data: any
  /** 响应头 */
  headers: Record<string, string | string[]>
  /** 响应的数字状态码 */
  status: number
  /** 响应状态的文本信息 */
  statusText: string
  /** 该响应的请求实例 */
  request: XMLHttpRequest
  /** 该请求的配置信息 */
  config?: AjaxRequiredOptions
}

错误信息

interface XHRErrorInfo extends Error {
  /** 异常是否来自请求被中止 */
  readonly isCancel: boolean
  /** 异常原因: 0-状态码 | 1-中止 | 2-错误 | 3-超时 */
  readonly reason: XHRState
  /** 该异常的请求实例 */
  readonly request: XMLHttpRequest
  /** 异常状态码的响应信息 */
  readonly response?: XHRResponse
  /** 该请求的配置信息 */
  config?: AjaxRequiredOptions
}

拦截器

interface XHRInterceptor {
  /** 请求拦截器 */
  request?:
    | ((options: AjaxOptions) => AjaxOptions)
    | ((options: AjaxOptions) => AjaxOptions)[]
  /** 成功拦截器 */
  response?:
    | ((response: any) => any)
    | ((response: any) => any)[]
  /** 失败拦截器 */
  error?:
    | ((error: XHRErrorInfo) => XHRErrorInfo)
    | ((error: XHRErrorInfo) => XHRErrorInfo)[]
}

示例

// 1. 请求拦截器,单个
interceptor.request = config => {
  config.timeout = 5
  return config
} // config.timeout = 5 (单位秒)

// 2. 请求拦截器,多个
interceptor.request = [
  config => {
    config.timeout = 3
    return config
  },
  config => {
    config.timeout = 5 * (config.timeout || 0)
    return config
  }
] // config.timeout = 15 (单位秒)

// 3. 成功拦截器,单个
interceptor.response = response => {
  response.statusText = 'zzzz'
  return response
} // response.statusText = 'zzzz'

// 4. 成功拦截器,多个
interceptor.response = [
  response => {
    response.statusText = 'xxxx'
    return response
  },
  response => {
    response.statusText += 'yyyy'
    return response
  }
] // response.statusText = xxxxyyyy

// 5. 失败拦截器,单个
interceptor.error = error => {
  error.message = 'error!!'
  return error
} // error.message = 'error!!'

// 6. 失败拦截器,多个
interceptor.error = [
  error => {
    error.message = 'error1'
    return error
  },
  error => {
    error.message += 'error2'
    return error
  }
] // error.message = 'error1error2'

默认配置

const defaults: AjaxRequiredOptions = {
  url: '',
  method: 'get',
  params: '', // user/:params
  query: '', // user?query
  body: null,
  baseURL: '',
  headers: {
    common: {
      Accept: 'application/json, text/plain, */*'
    }
  }, // 优先级由高到低: headers[name] > headers[method][name] > headers.common[name]
  timeout: 0,
  responseType: '',
  withCredentials: false,
  signal: '',
  transformQuery,
  transformBody,
  transformResponse,
  validateStatus,
  onUploadProgress: null,
  onDownloadProgress: null
}

取消请求

function cancel(signal?: string): void

重新初始化一个现有的请求

ajax('/reset') // 下一个请求发起后,该请求被取消,之后重新初始化
ajax('/reset') // 利用了 xhr.open() 的原始特性

中止所有激活的请求

ajax('/cancel1').catch(err => err.isCancel === true)
ajax('/cancel2').catch(err => err.isCancel === true)
cancel()
// 请求 /cancel1 和 /cancel2 同时被取消

中止特定的请求

ajax({ url: '/spec1', signal: 's1' }).catch(err => err.isCancel === true)
ajax({ url: '/spec2', signal: 's1' }).catch(err => err.isCancel === true)
ajax({ url: '/spec3', signal: 's2' })
cancel('s1')
// 请求 /spec1 和 /spec2 被取消,/spec3 还处于激活中

使用 request 发起请求

function request(config: XHROptions): Promise<XHRResponse>

是 ajax(config) 发起请求的核心方法(不触发拦截器,不格式化数据),适用于简单请求

示例

// get
request({ url }).then(res => console.log(res))
// post
request({ url, method: 'post', responseType: 'json' }).then(res =>
  console.log(res)
)

字符串化

/**
 * 字符串化,默认 mode = 'brackets'
 * 是 qs 以下模式的简化版
 * qs.stringify(obj, {
 *   format: 'RFC1738',
 *   arrayFormat: 'brackets',
 *   encodeValuesOnly: true,
 *   skipNulls: true
 * })
 */
function stringify(
  obj: Record<string, any>,
  mode?: 'brackets' | 'none' | 'indices'
): string

示例

stringify({ a: 1, b: ['x', { c: 'y' }] })
// a=1&b[]=x&b[][c]=y
stringify({ a: 1, b: ['x', { c: 'y' }] }, 'brackets')
// a=1&b[]=x&b[][c]=y
stringify({ a: 1, b: ['x', { c: 'y' }] }, 'none')
// a=1&b=x&b[c]=y
stringify({ a: 1, b: ['x', { c: 'y' }] }, 'indices')
// a=1&b[0]=x&b[1][c]=y

参考