axiosパッケージおよびフロントエンドインタフェース処理ポリシー

11000 ワード

インタフェースパッケージの必要性
大規模なフロントエンドプロジェクトでは、多くのインタフェースがデータ入力、流出を実現し、ブロックを付加し、状態管理と結合し、XSRF攻撃を防ぐなど、統一管理APIインタフェースは大規模なフロントエンドプロジェクトが直面しなければならない一環となっている.axiosは最もポピュラーなPromiseベースのHTTPライブラリとしてブラウザ側とサーバ側で同時に実行でき、ほとんどのフロントエンドプロジェクトの第一選択となっている.
POSTシーケンス化JSON.stringifyによって同様にシーケンス化を実現することができるが、複雑なObjectJSON.stringifyのサポートラインについてはqs.stringifyに及ばない.したがってqsというライブラリを導入することで、qsは深層ネストされたJSONおよびArray形式をシーケンス化し、APIパッケージをより多くのシーンに互換化することができます.
var a = {name:'hehe',age:10};
 qs.stringify(a)
// 'name=hehe&age=10'
JSON.stringify(a)
// '{"name":"hehe","age":10}'

例外:現在バックグラウンドエンジニアリングではbodyでjson,arrayなどを取得できることが多く,場合によってはバックグラウンドが直接読み取った文字列情報である可能性があるが,この場合qs.stringifyパッケージパラメータのJSONやArrayフォーマットでは取得できないため,JSON.stringifyを用いて処理する必要がある.
axiosの構成に対する処理
正式にaxiosの二次パッケージを行う前に、axiosの構成項目に対する処理を簡単に理解します.axiosが露出する方法から、axios.defaultsにconfigを構成してもよいし、ブロッキングに新しいinstance configを構成してもよいことがわかります.ソースコードを読むことで、axiosのconfig構成はmergeメソッドで実現されていることがわかります.
axios.create = function create(instanceConfig) {
  return createInstance(mergeConfig(axios.defaults, instanceConfig));
};

axios defaultおよび新しいinstanceのconfigに加えて、初期化されたデフォルトconfigも提供されます.
var DEFAULT_CONTENT_TYPE = {
  'Content-Type': 'application/x-www-form-urlencoded'
};

function setContentTypeIfUnset(headers, value) {
  if (!utils.isUndefined(headers) && utils.isUndefined(headers['Content-Type'])) {
    headers['Content-Type'] = value;
  }
}

axiosのconfigはこのような論理です.
1.デフォルトの初期化configとdefaultconfigはmergeを行う
2.最初のステップで得られた結果を新しいinstance上のconfigとmergeする
解析により,要求されたインタフェースを直接構成化処理することができ,様々なシーンに適応するためのより便利なステップ化が可能となる.
default config
axiosは私にdefaultシリーズの属性を提供して、直接axios.defaultのいくつかの属性に値を割り当てることができて、このaxios.defaultの値は使用するaxios要求に作用します;公式ドキュメントでは、デフォルトのbaseURLを設定したり、tokenベースのリクエストにtokenをheaderのAuthorizationに配置したり、postのリクエストタイプを設定したりするなど、いくつかの参考を提供してくれました.
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

要求ブロックおよび応答ブロック
優れたhttpリクエストライブラリとして、axiosは強力なリクエストブロックと応答ブロック機能を提供します.
ブロックを要求
//  vuex
import store from '@/store'
...
axios.interceptors.request.use(config => {
  // token    request header  
  const token = store.state.token;
  config.headers.common['Authorization'] = token
  // loading
  return config
}, error => {
  console.log(error)
  return Promise.reject(error)
})

ブロックによって要求の前置操作を実現することができ、例えば、ここではtokenをheaderに追加するのが一般的である.もちろんdefaultでtokenを処理してもよい.だからネット上の大部分のブロッキングに対する操作はdefaultsの中で実行することができて、何の違いもありません;個人的には、リクエスト前のブロックは、いくつかのタイマと組み合わせて、関連するプラグインの使用をフロントエンドで監視することができると考えています.
レスポンスブロック
応答ブロックの実行順序に注意し、axios.interceptors.response.useを実行してから正常な応答処理を実行する.
//      
axios.interceptors.response.use(    
    response => {
        //    response   HTTP    2XX   ,         200+JSON   JSON          
    },   
    //   error    HTTP     2XX   ,         HTTP status
    error => {            
        if (error.response.status) {            
            switch (error.response.status) {                
                case 401:                    
                //                    
                case 403:
                //                       
                    break; 
                case 404:
              // 404        
                    break;
                //     ,        
                default:
                //    
            }
            return Promise.reject(error.response);
        }
    }    
});

axios完全構成化
上記のaxiosの具体的なconfig分析により、merge結合パッケージ方法を追加することによって、多くのシーンの構成を実現することができる.例えば、クッキーをドメイン間で携帯するかどうか、loadingが付属しているかどうか、特殊なインタフェースを構成する要求が常に待機しているかどうかなどを実現することができる.
config.jsを作成できます
const configMap = {
  defaultConfig: {
    withCredentials: false,
    baseURL: path.baseUrl,
    headers: {
      post: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
    },
  },
  long: {
    timeout: 60000,
  },
  nocookie: {
    withCredentials: false,
  },
  ...

httpjsに導入することで
import configMap from './config'
import { showFullScreenLoading, tryHideFullScreenLoading } from './loading'
import merge from 'lodash.merge'
...
merge(axios.defaults, configMap['defaultConfig'])
function handleTypeString(type) {
  type.toLowerCase().split('-').map(item => merge(axios.defaults, configMap[item]))
}
export default {
  post(url, data, type) {
    handleTypeString(type)
    return axios({
      method: 'post',

これにより、複数のインタフェース要求の構成の組合せを実現することができ、後のものは前のものを上書きし、次々とaxios要求の完全な構成化処理を実現する.
vueでの使用
import http from "@/api/http";
import path from "@/api/path";
//  async await    
async test() {
  const res = await http.post(path.test, params, "long-nocookie");


バイアス関数を使ってもう1層包装するのが好きな人もいれば、呼び出し時に直接使用するようにパッケージを追加することもできます.
test(param)

グローバルloading状態の処理
loading.jsをカプセル化してurl要求インタフェースの一部にloading菊図が必要な場合を処理する.needLoadingCountを設定して、複数のloading要求インタフェース処理が必要な場合を記録する必要があります.
import { Loading } from 'element-ui';
let loading; 
function startLoading() { //   Element loading.tart   
  loading = Loading.service({
    lock: true,
    text: 'loading……',
    background: 'rgba(0, 0, 0, 0.5)',
  });
}
function endLoading() { //   Element loading.close   
  loading.close();
}
//  needLoadingCount   ,       loading    
let needLoadingCount = 0;
export function showLoading() {
  if (needLoadingCount === 0) {
    startLoading();
  }
  needLoadingCount++;//eslint-disable-line
}
export function tryHideLoading() {
  if (needLoadingCount >= 0) needLoadingCount--;//eslint-disable-line
  if (needLoadingCount === 0) {
    endLoading();
  }
}

httpでの構成
    if (type === 'long') {
      showFullScreenLoading()
      return axios(config).then(response=>{
         tryHideFullScreenLoading()
         rerurn response;
      })
    }
    //   loading axios  
     return axios(config)

多様な環境切り替えのパッケージ
前後端で分離されたspaシーンではaxiosのbaseUrlなどの各種環境パラメータが予め設定されている.それから静的ファイルにパッケージ化して、nginxあるいはtomcatのようなhttpサーバーにアップロードして、ローカル開発からテストまで、静的ファイルを提供して異なるバックグラウンドに使用して、異なるバックグラウンドで設定したインタフェースのアドレスが異なるかもしれません.一つ一つパッケージ化することを避けるために、私たちは異なるドメイン名環境のパッケージを構成する必要があります.

import merge from 'lodash.merge'
const path = {
  baseUrl: 'http://localhost:3000',
  login: '/users/login',
  test: '/test',
};
const pathMap = {
  'http://localhost:3001': { baseUrl: 'http://localhost:3001' },
    'http://localhost:3002': { baseUrl: 'http://localhost:3002',login:'/login' },
}

const getClientIdByLocation = () => {
  const { href } = window.location;
  const matchedKey = Object.keys(pathMap).filter(url => href.indexOf(url) > -1);
  merge(path, pathMap[matchedKey])
};
getClientIdByLocation();
export default path;

異なるurlに対応するpathオブジェクトをpathMapに直接配置することで,異なるurlに対応するbaseUrlや各シードのルーティング状況が異なる場合の処理を実現できる.
転載先:https://juejin.im/post/5cbc6b786fb9a0685b49049c