关闭

axios统一接口管理及优化

时间: 2019-12-03阅读: 726标签: axios

根据在项目的使用,发现有以下问题需要优化:

  1. withAxios导出的接口方法对象对编辑器来说是不透明的,所以代码提示功能缺失。
  2. 同一个方法调用多次,如何保证组件总是获取到最后一次的返回信息。


根据以上问题,采用了以下解决方案:

  1. 使用typescript的泛型解决。
  2. 调用同一个方法时,取消掉上次未完成的请求,这里使用axios的cancel方法。实现思路是在返回的方法对象中增加一个`${name}Cancel`的方法,保存取消上一次方法的回调,下次请求时固定调用这个取消方法以保证本次请求是当前唯一一个请求。(这里只提供axios层面的解决办法,不讨论其他办法,比如采用redux-saga的话可以使用takeLatest解决)


通过代码展示一下(react项目):

service.ts

import { IApiItem } from '@/configs/api/declares';
import withAxios from '@/utils/withAxios';

const api: IApiItem[] = [
  { name: 'getSummary', url: 'http://xx:8000/api/getSummary' },
  { name: 'getDetail', url: 'http://xx:8000/api/getDetail' },
  { name: 'getDetailChildren', url: 'http://xx:8000/api/getDetailChildren' },
  { name: 'getCurrentUser', url: 'http://xx:8000/api/getCurrentUser' },
];

interface IProdMonitorApi {
  getSummary: any;
  getDetail: any;
  getDetailChildren: any;
  getCurrentUser: any;
}

export default withAxios<IProdMonitorApi>(api);

withAxios.ts

function withAxios<T>(apiConfig: IApiItem[], usePassportOrigin: boolean = false): T {
  const serviceMap = {} as T;
  apiConfig.map(({ name, url, method = 'get', ...rest }: IApiItem) => {
    return (serviceMap[name] = async function(data = {}) {
      if (serviceMap[`${name}Cancel`] && typeof serviceMap[`${name}Cancel`] === 'function') {
        serviceMap[`${name}Cancel`]();
      }

      const source = axios.CancelToken.source();
      serviceMap[`${name}Cancel`] = () => {
        source.cancel(`已取消上次未完成请求:${name}`);
      };
      rest.cancelToken = source.token;

      let key = 'params';
      const apiMethod = method.toLowerCase();
      if (apiMethod === 'post' || apiMethod === 'put') {
        key = 'data';
      }
      let fetchUrl = url;
      if (url.indexOf('http') !== 0) {
        fetchUrl = usePassportOrigin
          ? NetworkUtils.passportOrigin + url
          : NetworkUtils.serverOrigin + url;
      }
      return axios({
        method,
        url: fetchUrl,
        [key]: data,
        fetchName: name,
        ...rest,
      } as AxiosRequestConfig);
    });
  });
  return serviceMap;
}

export default withAxios;

在需要使用接口的地方:

import Service from "./service.ts"
Service.getSummary(requestParams).then(...)


说明:

使用泛型虽然有了代码提示,但是额外增加了编码量,因为要手动维护一个方法接口,有利有弊吧,通过ts我还没有找到更好的方法。同事之前有过一个解决办法:接口管理使用对象的形式,然后withAxios修改这个对象各属性的getter,将getter指向通过axios包装后的方法,最终实现了本文相同的调用方式和代码提示,但这种方法有点hack的感觉。

cancel掉上一个接口这种方式保证了数据总是来源于最后一个请求接口,但有时可能会出现问题,比如:在同一个页面需要展示两种用户:common用户和admin用户,后端给的接口是/api/v1/user,当参数type=1时为common,type=2时为admin,如果我们把这个接口定义为一个方法getUser,在这个页面会同时发出两个请求:Service.getUser({type:1}),Service.getUser({type:2}),但是,由于withAxios会取消上一个相同方法的请求,那么很可能有一个请求被取消,解决办法是在service中定义为两种方法:getCommonUser和getAdminUser,将type直接写入url中。这样也符合我们语义化的目标。

站长推荐

1.云服务推荐: 国内主流云服务商,各类云产品的最新活动,优惠券领取。地址:阿里云腾讯云华为云

2.广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入

链接: http://www.fly63.com/article/detial/6739

关闭

vue axios不缓存get请求(防止返回304不更新数据)

最近做项目遇到一款浏览器,由于缓存了get请求,导致不管如何刷新,数据都不更新的问题。以下分享一下解决办法:解决思路就是给每一条get请求增加一个timestamp的参数,value为时间戳

封装axios

创建一个server目录,在该目录下创建index.js文件,配置axios:使用create方法创建axios实例,封装请求方法:创建一个api.js文件

axios请求失败自动重发

一般而言只要谈到异步,通常提到回调函数。JS里的Promise是一个强大的回调函数管理器。本文的实现方案正是利用了Promise的特性,在接口无权限时

vue中axios请求的封装

发送请求模块目录,@/api/url中存放的是每个模块的URL,使用webpack提供的require.context将src/api/url下后缀为js的所有文件引入,并整理出一个对象。整合common.js & product.js,最终得到的对象如下:

axios基于常见业务场景的二次封装

axios的二次封装,功能实现:1.兼容ie浏览器避免缓存2.减少或更新重复请求3.接口域名使用环境变量4.全局loading状态5.可关闭的全局错误提醒6.可开启携带全局分页参数

如何实现 axios 的自定义适配器 adapter

我们想基于 axios 扩展一些自己的数据请求方式(例如 mock 数据,某些 APP 内专属的数据请求方式等),并能够使用上 axios 提供的便捷功能,该怎么自定义一个适配器 adapter

Vue中axios的封装

axios 是 Vue 官方推荐的一个 HTTP 库,用 axios 官方简介来介绍它,就是:Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。作为一个优秀的 HTTP 库,axios 打败了曾经由 Vue 官方团队维护的 vue-resource

自己动手实现一个axios

作为一名前端er,对于数据请求的第三方工具axios,一定不会陌生,如果还是有没有用过,或者不了解的小伙伴,这里给你们准备了贴心的中文文档 ,聪明的你们一看就会~

vue封装axios和利用拦截器监控返回的token的变化和报错信息

步骤一:安装axios进入vue-cli;步骤二:新建一个httpConfig文件下,创建两个js文件,一个作为axios拦截器用,一个封装接口;步骤三:在serviceAPI.config.js中封装所有的API接口

axios 拦截器显示和关闭Loading

使用Loading分为2种情况,第一种是使用一些组件库自带的loading,另一种是使用我们自己写的loading,现分开介绍使用方法。使用element ui 带的Loading

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!