再談from屬性EncType與axios分裝—axios攔截器實現-源碼淺析

中古時代(若干年前)使用angular的時候,總結過《from屬性EncType提交數據的格式詳解—在angular中的應用html

在遠古ie興盛的時代,基本是fromData提交數據,ajax+jquery推進了時代的變革,當數據提交也大抵如此,直到angularJS到來,先後端才通用json形式,轉眼從react跳轉到vue(感受被Vue強暴),閒話打住前端

理論上,一套api接口,通常統一json格式,要麼統一fromData,可是,就是有不按套路出牌(後端屌啊),三個都有vue

application/x-www-form-urlencodednode

multipart/form-datareact

application/jsonjquery

 

同時,接口返回數據,理論上應該統一規劃,好比消息屬性(toast統一處理),數據分層,可是,淚崩ios

axios封裝是必須,可是,前端時候也得考慮下規範(架構設計)方面的問題——小白秉性暴露無遺web

 

看了axios源碼ajax

+axiosvuex

    index.js

    index.d.ts

    +lib

       axios.js

       +core

          Axios.js

axios自己就會檢測數據,匹配不一樣Content-Type

transformRequest: [function transformRequest(data, headers) {
  normalizeHeaderName(headers, 'Content-Type');
  if (utils.isFormData(data) ||
    utils.isArrayBuffer(data) ||
    utils.isBuffer(data) ||
    utils.isStream(data) ||
    utils.isFile(data) ||
    utils.isBlob(data)
  ) {
    return data;
  }
  if (utils.isArrayBufferView(data)) {
    return data.buffer;
  }
  if (utils.isURLSearchParams(data)) {
    setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8');
    return data.toString();
  }
  if (utils.isObject(data)) {
    setContentTypeIfUnset(headers, 'application/json;charset=utf-8');
    return JSON.stringify(data);
  }
  return data;
}],

可是,實際提交都是 Object類型,因而就得轉

第一種處理模式,就是prototype大法,

axios.postForm = function (url, data, config = null) {
  return new Promise(function (resolve, reject) {
    config = {
      method: 'post',
      url: url,
      data: () => {
        let fromData = new FormData();
        for (let i in data) {
          fromData.append(i,data[i])
        }
        return fromData;
      }
    };
    axios.request(config).then((response) => {
      resolve(response)
    }, err => {
      reject(err);
    })
  })
};

第二種,從新構造一個新的函數,call回調,或者

class http {
  constructor(config) {
    if (config) {
      return new Promise((resolve, reject) => {
        axios(config)
          .then(function (response) {

          });
      });
    }
  }
  static get(url, parma) {}
  static post(url, param) {}
}

 

發如今var axios= Create an instance of Axios,axios get post request 都是集中處理

Axios.prototype.request

// Provide aliases for supported request methods
utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {
  /*eslint func-names:0*/
  Axios.prototype[method] = function(url, config) {
    return this.request(utils.merge(config || {}, {
      method: method,
      url: url
    }));
  };
});

utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
  /*eslint func-names:0*/
  Axios.prototype[method] = function(url, data, config) {
    return this.request(utils.merge(config || {}, {
      method: method,
      url: url,
      data: data
    }));
  };
});

因而決定,經過增長一個屬性聲明,如:commitType:'form'

因而,就會有以下代碼

 

import axios from 'axios';
import queryString from 'queryString';//nodeJs內置,無需npm i
axios.interceptors.request.use(function (config) {
  //TODO 請求攔截
  /*store.commit('updateLoadingStatus', {isLoading: true});*/
  if (config.commitType) {
    if (config.commitType === 'form') {
      config.headers['Content-Type'] = 'application/x-www-form-urlencoded';
      config.transformRequest = [function (data) {
        return queryString.stringify(data);//利用對應方法轉換格式
      }]
    } else if (config.commitType === 'url') {
      config.headers['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
      config.transformRequest = [function (data) {
        return decodeURIComponent(data);
      }];
    }
  }

  console.log(config);
  return config;
}, function (error) {
  //請求錯誤時作些事
  return Promise.reject(error);
});

//響應攔截器即異常處理
axios.interceptors.response.use(response => {
  //TODO 統一處理邏輯
  //store.commit('updateLoadingStatus', {isLoading: false});
  if (response.data) {
    return response.data;
  }
  return response
}, err => {
  if (err && err.response) {
    //http狀態碼處理
    switch (err.response.status) {
      case 400:
        err.msg = '錯誤請求';
        break;
      case 401:
        err.msg = '未受權,請從新登陸';
        break;
      case 403:
        err.msg = '拒絕訪問';
        break;
      case 404:
        err.msg = '請求錯誤,未找到該資源';
        break;
      case 405:
        err.msg = '請求方法未容許';
        break;
      case 408:
        err.msg = '請求超時';
        break;
      case 500:
        err.msg = '服務器端出錯';
        break;
      case 501:
        err.msg = '網絡未實現';
        break;
      case 502:
        err.msg = '網絡錯誤';
        break;
      case 503:
        err.msg = '服務不可用';
        break;
      case 504:
        err.msg = '網絡超時';
        break;
      case 505:
        err.msg = 'http版本不支持該請求';
        break;
      default:
        err.msg = `鏈接錯誤${err.response.status}`
    }
  } else {
    err.msg = '鏈接到服務器失敗';
  }
  return Promise.resolve(err.response)
});
//超時時間
axios.defaults.timeout = 5000;

export default axios;

原文連接:https://www.zhoulujun.cn/html/webfront/ECMAScript/vue/8137.html(不定時更新)

文有不妥之處,請留言告知,謝謝!

拓展文章:

Vue中axios的使用技巧配置項詳解

Vue基於vuex、axios攔截器實現loading效果及axios的安裝配置

相關文章
相關標籤/搜索