封装http请求的新思路

198 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情

今天在群里看到了一个外企妹子秀的代码,粗看之下感觉很繁琐,细看之下真的有点东西,特此分享一下 首先看一下它的导出

假设这个文件是api.js image.png

这里其实使用了一个工厂函数,参数其实是一组API url地址的映射。

我们接着往下看,看一下他的output方法。

image.png 这里其实就是它的全部代码,其中makeOptions这个函数代码的是我自己想象实现的,不一定是他们的原始代码。

看到这里,我大概能想到他们这样封装的思路了:

  • API URL集中管理
  • 缓存请求函数,避免每次重新生成

在output这个函数里,首先遍历了options,就是一组API url地址的映射,参数本质上是一个数组。 [url,method,...params],第一项是url,第二项是请求方式,默认是get,在之后都是接口所需要的参数.

同时,通过闭包保存了一个reqMap这个变量,在内部赋值,比如reqMap.Login = xxx.

reqMap[name] = function(){
    if(reqOptions.method === 'get'){
        reqOptions.params = makeParams(arguments,settings.slice(2))
    } else {
        reqOptions.data = makeParams(arguments,settings.slice(2))
    }

    return axios(options)
}

我们看一下这个函数,这里的function并没有参数,而是使用arguments,这样就可以保持了一定的灵活性。我猜测,他们调用的时候,应当是一一对应的,params里第一个参数,就是arguments[0] 所以,我猜测他们的makeParams应当是这样实现的

const makeParams = (arg,params)=>{
    const data = {}
    params.forEach((key,index)=>{
        data[key] = arg[index]
    })
    return data
}

这样,当他调用的时候,其实是使用的reqMap,比如

import api from './api.js'
reqMap.Login('username')

思考了半天,我才算弄懂他们那边的封装的思路,和我的封装思路是完全不一样的。我一般会这样写

export const Login(username){
 const options = {
  method:'get',
  url:'/login',
  params:{
      username
  }
 }
 return axios(options)
}

使用的时候就是import {Login} from 'xx' 我这样写主要是因为每个接口都可能有不同的加密规则,因此我把每个接口变成一个函数。具体可以参考我很早的文章

我这一套也是主要跟花裤衩学习的,虽然每次起名字,引用比较麻烦,但用起来还算不错。但是url却没有做到集中管理,每次找url,我需要在xxx.js里搜索一下,虽然起名可以一定程度解决这个问题,但是有时候我起的变量名和后端接口并不一致。

其次,我每次使用Login,其实这个Login是已经赋值的变量,并没有做到缓存,这也是这个代码比较好的一点。 大家怎么看这段代码呢,欢迎文明讨论

PS:所有代码都是根据截图手敲的,如有错误,欢迎指正。