axios關於針對請求時長策略設計的思考

RobinsonZhang發表於2019-03-23

前言

在我們的業務請求中,有很多時候會針對有不同時長的需求策略性設定。這裡針對這個需求進行詳細的展開。

針對這種情況,我們的timout的一般是根據請求地址來的,所以核心處理技巧便是如何根據不同的request地址去設定不同的timeout.

我們之前設定的請求時長是十秒,並且是通過create的部分,整個專案只有一個instance的。

let _axios = axios.create({
  baseURL: apiProxyUrl,
  headers: { 'Content-Type': 'application/json' },
  transformRequest: [transformRequest],
  timeout: 10000 
})
複製程式碼

那麼既然需要處理request的地址部分,我建議針對長時長的地址單獨一個檔案維護,考慮到了以下兩點:

1 請求地址變多時,可以更好的定位以及維護
2 需要時,可以針對不同的微服務進行進一步的管理和配置
3 與下面請求時長的策略部分進行解耦
複製程式碼

主要結果是返回一個期望長時長地址的陣列。

/**
 * @author robin
 * @description maintain all long time api request paths
 */
 
/**
 * 使用者服務長時長地址陣列
 */
const userApiPaths = [] 

/**
 * 報表服務長時長地址陣列,如果你的微服務地址符合一個規律,可以這裡進行方法定義並返回
 */
const getTablesApiPaths = ()=>{
    return []
}

export default [
    '/house/list/houseSpaceInHouseSpaceManager'
].concat(userApiPaths).concat(getTablesApiPaths())
複製程式碼

簡單處理

我們知道axios本身的request支援攔截器的配置,那麼我們可以進行以下簡單的設定。

import longTimeApiEnum from './longTimeApiEnum'
// 請求攔截器
_axios.interceptors.request.use((config) => { 
  // 請求時長10分鐘
  const LONG_TIMEOUT = 600000 
  if (longTimeApiEnum.some(url => config.url.includes(url))) {
    config.timeout = LONG_TIMEOUT
  }
  return config
})
複製程式碼

此方法適用於大部分請求地址沒有規律性,適合用列舉維護相應地址的。

策略模式處理

當然如果你的長時長的api地址具有一定的正則可匹配性,也可以用正則來寫,並且把判斷的部分用策略模式獨立為一個方法,甚至一個檔案。

比如下面的例子:

// 根據微服務一級地址判斷
function judgeIsLongTimeApi(url){
  const strategy = {
      'user':function(url){
          if(url.includes('/users/data')) return true;
          return false
      },
      'table':function(url){
          if(url.includes('/table')) return true;
          return false
      }
  }

    const firstPath = url.split('/')[1];
    return strategy[firstPath] && strategy[firstPath](url);
    
}

// 使用
const LONG_TIMEOUT = 600000 
  if (judgeIsLongTimeApi(config.url)) {
    config.timeout = LONG_TIMEOUT
  }
複製程式碼

複雜的類處理

感覺上面的方式不夠逼格,或者有時候不是這麼簡單的改一個timeout,還需要改很多配置,比如說baseUrl等等。那麼你需要定義一個class。然後根據你的需求去自定義每個子類。大概是這樣的:這裡用到了class繼承。

import axios from 'axios';
class Api{
    constructor(){
        
    }
    nessaryFn(){
        throw Error('必須要實現的函式')
    }
    
    
}

class usualApi extends Api {
    constructor(){
        
    }
    nessaryFn(){
       //codes here
    }
}

class specialApi extends Api {
    constructor(){
        
    }
    nessaryFn(){
       //codes here
    }
}

// 再來一個策略模式 根據不同的情況 ,返回使用不同的api實現子類。

複製程式碼

小結

以上就是全部的關於axios部分的自定義維護時做的思考和實踐,已經完整的解決了自己的需求。

其他問題

  • 當axios的請求返回型別為非json型別,需要針對url進行特殊化配置的時候,相應的思路也是如此。
    if (exportXlsEnum.some(url  =>  config.url.includes(url))) {
    config.responseType  =  'blob'
    }
    複製程式碼

相關文章