前端代码设计之优雅的缓存Axios请求结果

开始设计

做为8年前端的我,在设计代码以前,我比较喜欢先想好怎么用,而后再去实现。想来想去,我以为像先下面这样使用会比较好一些:javascript

针对某个接口开启结果缓存

export function fetchList () {
  return request.cache('缓存key').get('/myinterface')
}
复制代码

调用接口的时候指定先从缓存中获取

fetchList()
  .cache() // 若是某状况须要强制调用接口来获取,则去掉该方法便可。
  .then(data => {})
  .catch(e => {})
  .finally(() => {})
复制代码

WHY?

为何这么使用?前端

  • 在接口调用方面,能够知足从缓存中获取和强制从接口中获取两种状况,这样使用起来会比较灵活一些。
  • 在接口定义方面,咱们必定须要一个缓存键。但这个缓存键为何不能直接默认使用接口参数?由于接口可能无需参数,那为何不能直接默认使用接口地址?由于restful风格下接口是同样的,只是请求方式不同。那为何不能直接使用接口+参数,这就考验设计者对设计的觉悟了。从设计角度来说,接口地址加参数的确能够标识惟一,但存在不可预见性,因此也不建议这么作。

代码实现

我不能说代码很简单,虽然代码量不大,但的确须要理一下。java

// 缓存请求结果
const buildCachePromise = (cacheKey, method, args, cacheImpl) => {
  return {
    __cacheImpl: cache[cacheImpl],
    __arguments: args,
    __result_promise: null,
    // 开启缓存
    cache () {
      const data = this.__cacheImpl.getJSON(cacheKey)
      if (data != null) {
        this.__result_promise = Promise.resolve(data)
      }
      if (this.__result_promise != null) {
        return this.__result_promise
      }
      return this
    },
    then () {
      return this.__access('then', arguments)
    },
    catch () {
      return this.__access('catch', arguments)
    },
    finally () {
      return this.__access('finally', arguments)
    },
    __access (methodName, args) {
      if (this.__result_promise != null) {
        return this.__result_promise
      }
      this.__result_promise = axiosInstance[method].apply(axiosInstance, this.__arguments)
      this.__result_promise.then(data => {
        this.__cacheImpl.setJSON(cacheKey, data)
        return data
      })
      return this.__result_promise[methodName].apply(this.__result_promise, args)
    }
  }
}
const methods = ['get', 'post', 'delete', 'put', 'head', 'options', 'patch', 'request']
axiosInstance.cache = function (cacheKey, isLocal = false) {
  if (cacheKey == null) {
    throw Error('Request cache key can not be null.')
  }
  const cacheAxiosInstance = {}
  for (const method of methods) {
    cacheAxiosInstance[method] = function () {
      return buildCachePromise(cacheKey, method, arguments, isLocal ? 'local' : 'session')
    }
  }
  return cacheAxiosInstance
}
复制代码

代码虽说是我本身写的,可是,我不得不说我本身再看一遍,我仍是得理一理。不过不重要,好用就行!这套代码是从个人开源框架Eva中提取出来的。后面还会跟你们介绍更多代码设计方面的内容。ios

Eva开源框架的主要目的呢,是可以进行快速开发项目,而且还能养成一套良好的开发规范,对于新手而言呢,也要作到是一套好的学习项目。git

欢迎star!github

关注我!和你一块儿探讨代码设计的艺术。axios