文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

ts如何封装axios

2023-07-05 11:37

关注

本篇内容主要讲解“ts如何封装axios”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“ts如何封装axios”吧!

什么样封装才是最合理的

别再用 promise 包了,好吗?

看了一下,很多人封装 axios 的时候都用 promise 包装了一层,甚至更有甚者用起了 try catch。为什么反对用 promise 包装,因为 axios 返回的就是个 promise ,脱裤子放屁,完全没必要????‍♀️。至于 try catch 这个是用于捕获未知错误的,比如 JSON.parse 的时候,有些字符串就是无法转换。记住一句话,滥用 try catch 和随地大小便没有区别。

一个 request 方法梭哈,噗!我一口老血????

部分人直接就一个 request 方法梭哈,所有参数与配置都写在一起,看起来一点也不清晰,简洁。请求有多种方式,getpostput...,最合理的请求方式应该是 instance[method](url, data, options)。对应 请求地址、请求参数、请求配置项,一目了然。

扩展我需要的请求,不要再 ts-ignore 了????

如果 ts-ignore 用多了,就会产生依赖性。不排除情况紧急急着上线,或者 类型处理 复杂的,但是在有时间的时候,还是得优化一下,作为程序员,追求优雅,永不过时。

求你了!把拦截器拿出来吧????

封装的时候我们都会封装一个请求类,但对应拦截器应该解耦出来。因为每个域名的拦截器处理可能不一致,写死的话封装请求类的意义也就没有了。

接口请求 then 里面又判断后端返回码判断请求是否成功,太狗血了!

看到下面这种代码,给我难受的啊。

api.post(url, data).then((res) => {  if (res.code === 1) {    // ...  } else {    // 全局消息提示    console.error(res.message)  }})

既然是一个 promise ,我们就应该知道 promise 只有成功或者失败。then 怎么会有成功错误的处理呢?then 里面就是请求成功,没有什么 if else,处理失败去 catch 里面处理去。这么喜欢写 if else,你是没写过单元测试是吧?

开整

OK,吐槽了这么多,这时候肯定就有人说了,光说谁不会啊,你整一个啊!????

瞧你这话说的,一点活没干,还让你白嫖了。你咋这么能呢?????

不过话说回来,我不要活在他人的评价里,我做这件事情不是因为你的讽刺或者吹捧,而是我自己要做????‍????。

接下来定一下要做的事情

开整之前先看看 axios 基本类型

// 这是 axios 请求类型定义,但是因为我们需要支持自定义配置,所以待会需要把它拓展一下export interface AxiosRequestConfig<D = any> {  url?: string;  method?: Method | string;  baseURL?: string;  transformRequest?: AxiosRequestTransformer | AxiosRequestTransformer[];  transformResponse?: AxiosResponseTransformer | AxiosResponseTransformer[];  headers?: (RawAxiosRequestHeaders & MethodsHeaders) | AxiosHeaders;  params?: any;  paramsSerializer?: ParamsSerializerOptions;  data?: D;  timeout?: Milliseconds;  timeoutErrorMessage?: string;  withCredentials?: boolean;  // ...}// 这是 axios 请求返回类型定义,里面类型需要处理,所以这个我们也得处理一下。export interface AxiosResponse<T = any, D = any> {  data: T;  status: number;  statusText: string;  headers: RawAxiosResponseHeaders | AxiosResponseHeaders;  // 这里的配置没有支持拓展,所以待会也得处理一下  config: InternalAxiosRequestConfig<D>;  request?: any;}// 所以我们只需要改造 3 个 axios 类型定义就行了// 另外我们需要定义下自己的拦截器 和 请求结果封装

Talk is cheap,show me the code.

代码也不多,就也不多解释了,基本注释都加上了。下面是全部代码。

import axios from 'axios'import type { AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios'// 定义一个常见后端请求返回type BaseApiResponse<T> = {  code: number  message: string  result: T}// 拓展 axios 请求配置,加入我们自己的配置interface RequestOptions {  // 是否全局展示请求 错误信息  globalErrorMessage?: boolean  // 是否全局展示请求 成功信息  globalSuccessMessage?: boolean}// 拓展自定义请求配置interface ExpandAxiosRequestConfig<D = any> extends AxiosRequestConfig<D> {  interceptorHooks?: InterceptorHooks  requestOptions?: RequestOptions}// 拓展 axios 请求配置interface ExpandInternalAxiosRequestConfig<D = any> extends InternalAxiosRequestConfig<D> {  interceptorHooks?: InterceptorHooks  requestOptions?: RequestOptions}// 拓展 axios 返回配置interface ExpandAxiosResponse<T = any, D = any> extends AxiosResponse<T, D> {  config: ExpandInternalAxiosRequestConfig<D>}export interface InterceptorHooks {  requestInterceptor?: (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig  requestInterceptorCatch?: (error: any) => any  responseInterceptor?: (response: AxiosResponse) => AxiosResponse | Promise<AxiosResponse>  responseInterceptorCatch?: (error: any) => any}// 导出Request类,可以用来自定义传递配置来创建实例export default class Request {  // axios 实例  private _instance: AxiosInstance  // 默认配置  private _defaultConfig: ExpandAxiosRequestConfig = {    baseURL: '/api',    timeout: 5000,    requestOptions: {      globalErrorMessage: true,      globalSuccessMessage: false    }  }  private _interceptorHooks?: InterceptorHooks  constructor(config: ExpandAxiosRequestConfig) {    // 使用axios.create创建axios实例    this._instance = axios.create(Object.assign(this._defaultConfig, config))    this._interceptorHooks = config.interceptorHooks    this.setupInterceptors()  }  // 通用拦截,在初始化时就进行注册和运行,对基础属性进行处理  private setupInterceptors() {    this._instance.interceptors.request.use(this._interceptorHooks?.requestInterceptor, this._interceptorHooks?.requestInterceptorCatch)    this._instance.interceptors.response.use(this._interceptorHooks?.responseInterceptor, this._interceptorHooks?.responseInterceptorCatch)  }  // 定义核心请求  public request(config: ExpandAxiosRequestConfig): Promise<AxiosResponse> {    // !!!⚠️ 注意:axios 已经将请求使用 promise 封装过了    // 这里直接返回,不需要我们再使用 promise 封装一层    return this._instance.request(config)  }  public get<T = any>(url: string, config?: ExpandAxiosRequestConfig): Promise<AxiosResponse<BaseApiResponse<T>>> {    return this._instance.get(url, config)  }  public post<T = any>(url: string, data?: any, config?: ExpandAxiosRequestConfig): Promise<T> {    return this._instance.post(url, data, config)  }  public put<T = any>(url: string, data?: any, config?: ExpandAxiosRequestConfig): Promise<T> {    return this._instance.put(url, data, config)  }  public delete<T = any>(url: string, config?: ExpandAxiosRequestConfig): Promise<T> {    return this._instance.delete(url, config)  }}

以及使用的 demo。这个保姆级服务满意吗?

// 请求拦截器const transform: InterceptorHooks = {  requestInterceptor(config) {    // 请求头部处理,如添加 token    const token = 'token-value'    if (token) {      config!.headers!.Authorization = token    }    return config  },  requestInterceptorCatch(err) {    // 请求错误,这里可以用全局提示框进行提示    return Promise.reject(err)  },  responseInterceptor(result) {    // 因为 axios 返回不支持扩展自定义配置,需要自己断言一下    const res = result as ExpandAxiosResponse    // 与后端约定的请求成功码    const SUCCESS_CODE = 1    if (res.status !== 200) return Promise.reject(res)    if (res.data.code !== SUCCESS_CODE) {      if (res.config.requestOptions?.globalErrorMessage) {        // 这里全局提示错误        console.error(res.data.message)      }      return Promise.reject(res.data)    }    if (res.config.requestOptions?.globalSuccessMessage) {      // 这里全局提示请求成功      console.log(res.data.message)    }    // 请求返回值,建议将 返回值 进行解构    return res.data.result  },  responseInterceptorCatch(err) {    // 这里用来处理 http 常见错误,进行全局提示    const mapErrorStatus = new Map([      [400, '请求方式错误'],      [401, '请重新登录'],      [403, '拒绝访问'],      [404, '请求地址有误'],      [500, '服务器出错']    ])    const message = mapErrorStatus.get(err.response.status) || '请求出错,请稍后再试'    // 此处全局报错    console.error(message)    return Promise.reject(err.response)  }}// 具体使用时先实例一个请求对象const request = new Request({  baseURL: '/api',  timeout: 5000,  interceptorHooks: transform})// 定义请求返回interface ResModel {  str: string  num: number}// 发起请求request  .post<ResModel>(    '/abc',    {      a: 'aa',      b: 'bb'    },    {      requestOptions: {        globalErrorMessage: true      }    }  )  .then((res) => {    console.log('res: ', res)    console.log(res.str)  })

可以看到鼠标浮上去就能看到定义了,完美!

ts如何封装axios

到此,相信大家对“ts如何封装axios”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯