fetch封装

481 阅读1分钟

使用 React Hooks 和 fetch API 封装的简单的 HTTP 请求工具。

167282.webp

import qs from 'qs'
import { useCallback } from 'react'

// 请求配置接口 
interface IRequestConfig extends RequestInit {
  data?: Record<string, unknown> // 请求数据对象
  token?: string // 认证令牌
}

const baseUrl = process.env.REACT_APP_BASE_URL // 根据项目环境匹配接口
let controller: AbortController // 请求控制器 用于取消请求

// 发送HTTP请求的函数 
const Http = (url: string, { data, token, ...customerConfig }: IRequestConfig) => {
  // 如果之前有正在进行的请求,则取消它
  if (controller) {
    controller.abort()
  }
  controller = new AbortController()

  // 构建请求配置对象
  const config: RequestInit = {
    method: 'GET',
    headers: {
      'Content-Type': 'application/json',
      Authorization: token ? `Bearer ${token}` : '',
    },
    signal: controller.signal,
    ...customerConfig,
  }

  // 处理GET请求的查询参数和其他请求方式的请求体
  if (config.method?.toUpperCase() === 'GET') {
    url += `?${qs.stringify(data)}`
  } else {
    config.body = data ? JSON.stringify(data) : ''
  }

  // 发送请求并处理响应
  return window
    .fetch(`${baseUrl}${url}`, config)
    .then(async (response) => {
      // 返回状态码按具体情况修改
      if (response.status === 401) {
        return Promise.reject('没权限')
      }
      const data = await response.json()
      if (response.ok && data.code === 200) {
        return Promise.resolve(data.data)
      } else {
        return Promise.reject(data)
      }
    })
    .catch((error) => {
      return Promise.reject(error)
    })
}

// 自定义Hook,用于在组件中进行HTTP请求
export const useHttp = () => {
  const token = '1111' // 动态获取token认证令牌

  return useCallback(
    (...[url, config]: Parameters<typeof Http>) => {
      return Http(url, { token, ...config })
    },
    [token],
  )
}

// 带超时的请求
const httpWithTimeout = (...[url, config]: Parameters<typeof Http>) => {
  const timeoutPromise = (delay: number = 3000) => {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        reject('请求超时')
      }, delay)
    })
  }

  return Promise.race([timeoutPromise(5000), Http(url, config)])
}