国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

vue中axios的介紹及封裝(看這一篇就夠了!)

這篇具有很好參考價值的文章主要介紹了vue中axios的介紹及封裝(看這一篇就夠了!)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

vue axios封裝和使用,Vue.js入門到實戰(zhàn),vue.js,javascript,前端

???個人主頁:前端青山
??系列專欄:Vue篇
??人終將被年少不可得之物困其一生

依舊青山,本期給大家?guī)韛ue篇專欄內(nèi)容:vue-axios

目錄

一、axios是什么

二、實現(xiàn)一個簡易版axios

三、源碼分析

小結(jié)

四、axios的使用

特性

基本使用

五、為什么要封裝

六、如何封裝

設置接口請求前綴

設置請求頭與超時時間

封裝請求方法

請求攔截器

響應攔截器

vue axios封裝和使用,Vue.js入門到實戰(zhàn),vue.js,javascript,前端

一、axios是什么

關于axios的基本使用,上篇文章已經(jīng)有所涉及,這里再稍微回顧下:

發(fā)送請求

import axios from 'axios';
?
axios(config) // 直接傳入配置
axios(url[, config]) // 傳入url和配置
axios[method](url[, option]) // 直接調(diào)用請求方式方法,傳入url和配置
axios[method](url[, data[, option]]) // 直接調(diào)用請求方式方法,傳入data、url和配置
axios.request(option) // 調(diào)用 request 方法
?
const axiosInstance = axios.create(config)
// axiosInstance 也具有以上 axios 的能力
?
axios.all([axiosInstance1, axiosInstance2]).then(axios.spread(response1, response2))
// 調(diào)用 all 和傳入 spread 回調(diào)

請求攔截器

axios.interceptors.request.use(function (config) {
 ? ?// 這里寫發(fā)送請求前處理的代碼
 ? ?return config;
}, function (error) {
 ? ?// 這里寫發(fā)送請求錯誤相關的代碼
 ? ?return Promise.reject(error);
});

響應攔截器

axios.interceptors.response.use(function (response) {
 ? ?// 這里寫得到響應數(shù)據(jù)后處理的代碼
 ? ?return response;
}, function (error) {
 ? ?// 這里寫得到錯誤響應處理的代碼
 ? ?return Promise.reject(error);
});

取消請求

// 方式一
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
?
axios.get('xxxx', {
 ?cancelToken: source.token
})
// 取消請求 (請求原因是可選的)
source.cancel('主動取消請求');
?
// 方式二
const CancelToken = axios.CancelToken;
let cancel;
?
axios.get('xxxx', {
 ?cancelToken: new CancelToken(function executor(c) {
 ? ?cancel = c;
  })
});
cancel('主動取消請求');

二、實現(xiàn)一個簡易版axios

構建一個Axios構造函數(shù),核心代碼為request

class Axios {
 ? ?constructor() {
?
 ?  }
?
 ? ?request(config) {
 ? ? ? ?return new Promise(resolve => {
 ? ? ? ? ? ?const {url = '', method = 'get', data = {}} = config;
 ? ? ? ? ? ?// 發(fā)送ajax請求
 ? ? ? ? ? ?const xhr = new XMLHttpRequest();
 ? ? ? ? ? ?xhr.open(method, url, true);
 ? ? ? ? ? ?xhr.onload = function() {
 ? ? ? ? ? ? ? ?console.log(xhr.responseText)
 ? ? ? ? ? ? ? ?resolve(xhr.responseText);
 ? ? ? ? ?  }
 ? ? ? ? ? ?xhr.send(data);
 ? ? ?  })
 ?  }
}

導出axios實例

// 定義get,post...方法,掛在到Axios原型上
const methodsArr = ['get', 'delete', 'head', 'options', 'put', 'patch', 'post'];
methodsArr.forEach(met => {
 ? ?Axios.prototype[met] = function() {
 ? ? ? ?console.log('執(zhí)行'+met+'方法');
 ? ? ? ?// 處理單個方法
 ? ? ? ?if (['get', 'delete', 'head', 'options'].includes(met)) { // 2個參數(shù)(url[, config])
 ? ? ? ? ? ?return this.request({
 ? ? ? ? ? ? ? ?method: met,
 ? ? ? ? ? ? ? ?url: arguments[0],
 ? ? ? ? ? ? ? ?...arguments[1] || {}
 ? ? ? ? ?  })
 ? ? ?  } else { // 3個參數(shù)(url[,data[,config]])
 ? ? ? ? ? ?return this.request({
 ? ? ? ? ? ? ? ?method: met,
 ? ? ? ? ? ? ? ?url: arguments[0],
 ? ? ? ? ? ? ? ?data: arguments[1] || {},
 ? ? ? ? ? ? ? ?...arguments[2] || {}
 ? ? ? ? ?  })
 ? ? ?  }
?
 ?  }
})

上述就已經(jīng)能夠?qū)崿F(xiàn)axios({ })這種方式的請求

下面是來實現(xiàn)下axios.method()這種形式的請求

// 定義get,post...方法,掛在到Axios原型上
const methodsArr = ['get', 'delete', 'head', 'options', 'put', 'patch', 'post'];
methodsArr.forEach(met => {
 ? ?Axios.prototype[met] = function() {
 ? ? ? ?console.log('執(zhí)行'+met+'方法');
 ? ? ? ?// 處理單個方法
 ? ? ? ?if (['get', 'delete', 'head', 'options'].includes(met)) { // 2個參數(shù)(url[, config])
 ? ? ? ? ? ?return this.request({
 ? ? ? ? ? ? ? ?method: met,
 ? ? ? ? ? ? ? ?url: arguments[0],
 ? ? ? ? ? ? ? ?...arguments[1] || {}
 ? ? ? ? ?  })
 ? ? ?  } else { // 3個參數(shù)(url[,data[,config]])
 ? ? ? ? ? ?return this.request({
 ? ? ? ? ? ? ? ?method: met,
 ? ? ? ? ? ? ? ?url: arguments[0],
 ? ? ? ? ? ? ? ?data: arguments[1] || {},
 ? ? ? ? ? ? ? ?...arguments[2] || {}
 ? ? ? ? ?  })
 ? ? ?  }
?
 ?  }
})

Axios.prototype上的方法搬運到request

首先實現(xiàn)個工具類,實現(xiàn)將b方法混入到a,并且修改this指向

const utils = {
 ?extend(a,b, context) {
 ? ?for(let key in b) {
 ? ? ?if (b.hasOwnProperty(key)) {
 ? ? ? ?if (typeof b[key] === 'function') {
 ? ? ? ? ?a[key] = b[key].bind(context);
 ? ? ?  } else {
 ? ? ? ? ?a[key] = b[key]
 ? ? ?  }
 ? ?  }
 ? ? ?
 ?  }
  }
}

修改導出的方法

function CreateAxiosFn() {
  let axios = new Axios();
  
  let req = axios.request.bind(axios);
  // 增加代碼
  utils.extend(req, Axios.prototype, axios)
  
  return req;
}

構建攔截器的構造函數(shù)

class InterceptorsManage {
  constructor() {
    this.handlers = [];
  }

  use(fullfield, rejected) {
    this.handlers.push({
      fullfield,
      rejected
    })
  }
}

實現(xiàn)axios.interceptors.response.useaxios.interceptors.request.use

class Axios {
    constructor() {
        // 新增代碼
        this.interceptors = {
            request: new InterceptorsManage,
            response: new InterceptorsManage
        }
    }

    request(config) {
 		...
    }
}

執(zhí)行語句axios.interceptors.response.useaxios.interceptors.request.use的時候,實現(xiàn)獲取axios實例上的interceptors對象,然后再獲取responserequest攔截器,再執(zhí)行對應的攔截器的use方法

Axios上的方法和屬性搬到request過去

function CreateAxiosFn() {
  let axios = new Axios();
  
  let req = axios.request.bind(axios);
  // 混入方法, 處理axios的request方法,使之擁有get,post...方法
  utils.extend(req, Axios.prototype, axios)
  // 新增代碼
  utils.extend(req, axios)
  return req;
}

現(xiàn)在request也有了interceptors對象,在發(fā)送請求的時候,會先獲取request攔截器的handlers的方法來執(zhí)行

首先將執(zhí)行ajax的請求封裝成一個方法

request(config) {
    this.sendAjax(config)
}
sendAjax(config){
    return new Promise(resolve => {
        const {url = '', method = 'get', data = {}} = config;
        // 發(fā)送ajax請求
        console.log(config);
        const xhr = new XMLHttpRequest();
        xhr.open(method, url, true);
        xhr.onload = function() {
            console.log(xhr.responseText)
            resolve(xhr.responseText);
        };
        xhr.send(data);
    })
}

獲得handlers中的回調(diào)

request(config) {
    // 攔截器和請求組裝隊列
    let chain = [this.sendAjax.bind(this), undefined] // 成對出現(xiàn)的,失敗回調(diào)暫時不處理

    // 請求攔截
    this.interceptors.request.handlers.forEach(interceptor => {
        chain.unshift(interceptor.fullfield, interceptor.rejected)
    })

    // 響應攔截
    this.interceptors.response.handlers.forEach(interceptor => {
        chain.push(interceptor.fullfield, interceptor.rejected)
    })

    // 執(zhí)行隊列,每次執(zhí)行一對,并給promise賦最新的值
    let promise = Promise.resolve(config);
    while(chain.length > 0) {
        promise = promise.then(chain.shift(), chain.shift())
    }
    return promise;
}

chains大概是['fulfilled1','reject1','fulfilled2','reject2','this.sendAjax','undefined','fulfilled2','reject2','fulfilled1','reject1']這種形式

這樣就能夠成功實現(xiàn)一個簡易版axios

三、源碼分析

首先看看目錄結(jié)構

vue axios封裝和使用,Vue.js入門到實戰(zhàn),vue.js,javascript,前端

axios發(fā)送請求有很多實現(xiàn)的方法,實現(xiàn)入口文件為axios.js

function createInstance(defaultConfig) {
  var context = new Axios(defaultConfig);

  // instance指向了request方法,且上下文指向context,所以可以直接以 instance(option) 方式調(diào)用 
  // Axios.prototype.request 內(nèi)對第一個參數(shù)的數(shù)據(jù)類型判斷,使我們能夠以 instance(url, option) 方式調(diào)用
  var instance = bind(Axios.prototype.request, context);

  // 把Axios.prototype上的方法擴展到instance對象上,
  // 并指定上下文為context,這樣執(zhí)行Axios原型鏈上的方法時,this會指向context
  utils.extend(instance, Axios.prototype, context);

  // Copy context to instance
  // 把context對象上的自身屬性和方法擴展到instance上
  // 注:因為extend內(nèi)部使用的forEach方法對對象做for in 遍歷時,只遍歷對象本身的屬性,而不會遍歷原型鏈上的屬性
  // 這樣,instance 就有了  defaults、interceptors 屬性。
  utils.extend(instance, context);
  return instance;
}

// Create the default instance to be exported 創(chuàng)建一個由默認配置生成的axios實例
var axios = createInstance(defaults);

// Factory for creating new instances 擴展axios.create工廠函數(shù),內(nèi)部也是 createInstance
axios.create = function create(instanceConfig) {
  return createInstance(mergeConfig(axios.defaults, instanceConfig));
};

// Expose all/spread
axios.all = function all(promises) {
  return Promise.all(promises);
};

axios.spread = function spread(callback) {
  return function wrap(arr) {
    return callback.apply(null, arr);
  };
};
module.exports = axios;

主要核心是 Axios.prototype.request,各種請求方式的調(diào)用實現(xiàn)都是在 request 內(nèi)部實現(xiàn)的, 簡單看下 request 的邏輯

Axios.prototype.request = function request(config) {
  // Allow for axios('example/url'[, config]) a la fetch API
  // 判斷 config 參數(shù)是否是 字符串,如果是則認為第一個參數(shù)是 URL,第二個參數(shù)是真正的config
  if (typeof config === 'string') {
    config = arguments[1] || {};
    // 把 url 放置到 config 對象中,便于之后的 mergeConfig
    config.url = arguments[0];
  } else {
    // 如果 config 參數(shù)是否是 字符串,則整體都當做config
    config = config || {};
  }
  // 合并默認配置和傳入的配置
  config = mergeConfig(this.defaults, config);
  // 設置請求方法
  config.method = config.method ? config.method.toLowerCase() : 'get';
  /*
    something... 此部分會在后續(xù)攔截器單獨講述
  */
};

// 在 Axios 原型上掛載 'delete', 'get', 'head', 'options' 且不傳參的請求方法,實現(xiàn)內(nèi)部也是 request
utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {
  Axios.prototype[method] = function(url, config) {
    return this.request(utils.merge(config || {}, {
      method: method,
      url: url
    }));
  };
});

// 在 Axios 原型上掛載 'post', 'put', 'patch' 且傳參的請求方法,實現(xiàn)內(nèi)部同樣也是 request
utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
  Axios.prototype[method] = function(url, data, config) {
    return this.request(utils.merge(config || {}, {
      method: method,
      url: url,
      data: data
    }));
  };
});

request入口參數(shù)為config,可以說config貫徹了axios的一生

axios 中的 config主要分布在這幾個地方:

  • 默認配置 defaults.js

  • config.method默認為 get

  • 調(diào)用 createInstance 方法創(chuàng)建 axios實例,傳入的config

  • 直接或間接調(diào)用 request 方法,傳入的 confi

?
// axios.js
// 創(chuàng)建一個由默認配置生成的axios實例
var axios = createInstance(defaults);

// 擴展axios.create工廠函數(shù),內(nèi)部也是 createInstance
axios.create = function create(instanceConfig) {
  return createInstance(mergeConfig(axios.defaults, instanceConfig));
};

// Axios.js
// 合并默認配置和傳入的配置
config = mergeConfig(this.defaults, config);
// 設置請求方法
config.method = config.method ? config.method.toLowerCase() : 'get';

?

從源碼中,可以看到優(yōu)先級:默認配置對象default < method:get < Axios的實例屬性this.default < request參數(shù)

下面重點看看request方法

Axios.prototype.request = function request(config) {
  /*
    先是 mergeConfig ... 等,不再闡述
  */
  // Hook up interceptors middleware 創(chuàng)建攔截器鏈. dispatchRequest 是重中之重,后續(xù)重點
  var chain = [dispatchRequest, undefined];

  // push各個攔截器方法 注意:interceptor.fulfilled 或 interceptor.rejected 是可能為undefined
  this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
    // 請求攔截器逆序 注意此處的 forEach 是自定義的攔截器的forEach方法
    chain.unshift(interceptor.fulfilled, interceptor.rejected);
  });

  this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
    // 響應攔截器順序 注意此處的 forEach 是自定義的攔截器的forEach方法
    chain.push(interceptor.fulfilled, interceptor.rejected);
  });

  // 初始化一個promise對象,狀態(tài)為resolved,接收到的參數(shù)為已經(jīng)處理合并過的config對象
  var promise = Promise.resolve(config);

  // 循環(huán)攔截器的鏈
  while (chain.length) {
    promise = promise.then(chain.shift(), chain.shift()); // 每一次向外彈出攔截器
  }
  // 返回 promise
  return promise;
};

攔截器interceptors是在構建axios實例化的屬性

function Axios(instanceConfig) {
  this.defaults = instanceConfig;
  this.interceptors = {
    request: new InterceptorManager(), // 請求攔截
    response: new InterceptorManager() // 響應攔截
  };
}
InterceptorManager構造函數(shù)

// 攔截器的初始化 其實就是一組鉤子函數(shù)
function InterceptorManager() {
  this.handlers = [];
}

// 調(diào)用攔截器實例的use時就是往鉤子函數(shù)中push方法
InterceptorManager.prototype.use = function use(fulfilled, rejected) {
  this.handlers.push({
    fulfilled: fulfilled,
    rejected: rejected
  });
  return this.handlers.length - 1;
};

// 攔截器是可以取消的,根據(jù)use的時候返回的ID,把某一個攔截器方法置為null
// 不能用 splice 或者 slice 的原因是 刪除之后 id 就會變化,導致之后的順序或者是操作不可控
InterceptorManager.prototype.eject = function eject(id) {
  if (this.handlers[id]) {
    this.handlers[id] = null;
  }
};

// 這就是在 Axios的request方法中 中循環(huán)攔截器的方法 forEach 循環(huán)執(zhí)行鉤子函數(shù)
InterceptorManager.prototype.forEach = function forEach(fn) {
  utils.forEach(this.handlers, function forEachHandler(h) {
    if (h !== null) {
      fn(h);
    }
  });
}

請求攔截器方法是被 unshift到攔截器中,響應攔截器是被push到攔截器中的。最終它們會拼接上一個叫dispatchRequest的方法被后續(xù)的 promise 順序執(zhí)行

var utils = require('./../utils');
var transformData = require('./transformData');
var isCancel = require('../cancel/isCancel');
var defaults = require('../defaults');
var isAbsoluteURL = require('./../helpers/isAbsoluteURL');
var combineURLs = require('./../helpers/combineURLs');

// 判斷請求是否已被取消,如果已經(jīng)被取消,拋出已取消
function throwIfCancellationRequested(config) {
  if (config.cancelToken) {
    config.cancelToken.throwIfRequested();
  }
}

module.exports = function dispatchRequest(config) {
  throwIfCancellationRequested(config);

  // 如果包含baseUrl, 并且不是config.url絕對路徑,組合baseUrl以及config.url
  if (config.baseURL && !isAbsoluteURL(config.url)) {
    // 組合baseURL與url形成完整的請求路徑
    config.url = combineURLs(config.baseURL, config.url);
  }

  config.headers = config.headers || {};

  // 使用/lib/defaults.js中的transformRequest方法,對config.headers和config.data進行格式化
  // 比如將headers中的Accept,Content-Type統(tǒng)一處理成大寫
  // 比如如果請求正文是一個Object會格式化為JSON字符串,并添加application/json;charset=utf-8的Content-Type
  // 等一系列操作
  config.data = transformData(
    config.data,
    config.headers,
    config.transformRequest
  );

  // 合并不同配置的headers,config.headers的配置優(yōu)先級更高
  config.headers = utils.merge(
    config.headers.common || {},
    config.headers[config.method] || {},
    config.headers || {}
  );

  // 刪除headers中的method屬性
  utils.forEach(
    ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],
    function cleanHeaderConfig(method) {
      delete config.headers[method];
    }
  );

  // 如果config配置了adapter,使用config中配置adapter的替代默認的請求方法
  var adapter = config.adapter || defaults.adapter;

  // 使用adapter方法發(fā)起請求(adapter根據(jù)瀏覽器環(huán)境或者Node環(huán)境會有不同)
  return adapter(config).then(
    // 請求正確返回的回調(diào)
    function onAdapterResolution(response) {
      // 判斷是否以及取消了請求,如果取消了請求拋出以取消
      throwIfCancellationRequested(config);

      // 使用/lib/defaults.js中的transformResponse方法,對服務器返回的數(shù)據(jù)進行格式化
      // 例如,使用JSON.parse對響應正文進行解析
      response.data = transformData(
        response.data,
        response.headers,
        config.transformResponse
      );

      return response;
    },
    // 請求失敗的回調(diào)
    function onAdapterRejection(reason) {
      if (!isCancel(reason)) {
        throwIfCancellationRequested(config);

        if (reason && reason.response) {
          reason.response.data = transformData(
            reason.response.data,
            reason.response.headers,
            config.transformResponse
          );
        }
      }
      return Promise.reject(reason);
    }
  );
};

再來看看axios是如何實現(xiàn)取消請求的,實現(xiàn)文件在CancelToken.js

function CancelToken(executor) {
  if (typeof executor !== 'function') {
    throw new TypeError('executor must be a function.');
  }
  // 在 CancelToken 上定義一個 pending 狀態(tài)的 promise ,將 resolve 回調(diào)賦值給外部變量 resolvePromise
  var resolvePromise;
  this.promise = new Promise(function promiseExecutor(resolve) {
    resolvePromise = resolve;
  });

  var token = this;
  // 立即執(zhí)行 傳入的 executor函數(shù),將真實的 cancel 方法通過參數(shù)傳遞出去。
  // 一旦調(diào)用就執(zhí)行 resolvePromise 即前面的 promise 的 resolve,就更改promise的狀態(tài)為 resolve。
  // 那么xhr中定義的 CancelToken.promise.then方法就會執(zhí)行, 從而xhr內(nèi)部會取消請求
  executor(function cancel(message) {
    // 判斷請求是否已經(jīng)取消過,避免多次執(zhí)行
    if (token.reason) {
      return;
    }
    token.reason = new Cancel(message);
    resolvePromise(token.reason);
  });
}

CancelToken.source = function source() {
  // source 方法就是返回了一個 CancelToken 實例,與直接使用 new CancelToken 是一樣的操作
  var cancel;
  var token = new CancelToken(function executor(c) {
    cancel = c;
  });
  // 返回創(chuàng)建的 CancelToken 實例以及取消方法
  return {
    token: token,
    cancel: cancel
  };
};

實際上取消請求的操作是在 xhr.js 中也有響應的配合的

if (config.cancelToken) {
    config.cancelToken.promise.then(function onCanceled(cancel) {
        if (!request) {
            return;
        }
        // 取消請求
        request.abort();
        reject(cancel);
    });
}

巧妙的地方在 CancelTokenexecutor 函數(shù),通過resolve函數(shù)的傳遞與執(zhí)行,控制promise的狀態(tài)

小結(jié)

vue axios封裝和使用,Vue.js入門到實戰(zhàn),vue.js,javascript,前端

四、axios的使用

vue axios封裝和使用,Vue.js入門到實戰(zhàn),vue.js,javascript,前端

axios 是一個輕量的 HTTP客戶端

基于 XMLHttpRequest 服務來執(zhí)行 HTTP 請求,支持豐富的配置,支持 Promise,支持瀏覽器端和 Node.js 端。自Vue2.0起,尤大宣布取消對 vue-resource 的官方推薦,轉(zhuǎn)而推薦 axios?,F(xiàn)在 axios 已經(jīng)成為大部分 Vue 開發(fā)者的首選

特性

  • 從瀏覽器中創(chuàng)建 XMLHttpRequests

  • node.js 創(chuàng)建 http請求

  • 支持 Promise API

  • 攔截請求和響應

  • 轉(zhuǎn)換請求數(shù)據(jù)和響應數(shù)據(jù)

  • 取消請求

  • 自動轉(zhuǎn)換JSON 數(shù)據(jù)

  • 客戶端支持防御XSRF

基本使用

安裝

// 項目中安裝
npm install axios --S
// cdn 引入
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

導入

import axios from 'axios'

發(fā)送請求

axios({ ? ? ? ?
 ?url:'xxx', ? ?// 設置請求的地址
 ?method:"GET", // 設置請求方法
 ?params:{ ? ? ?// get請求使用params進行參數(shù)憑借,如果是post請求用data
 ? ?type: '',
 ? ?page: 1
  }
}).then(res => { ?
 ?// res為后端返回的數(shù)據(jù)
 ?console.log(res); ? 
})

并發(fā)請求axios.all([])

function getUserAccount() {
 ? ?return axios.get('/user/12345');
}
?
function getUserPermissions() {
 ? ?return axios.get('/user/12345/permissions');
}
?
axios.all([getUserAccount(), getUserPermissions()])
 ?  .then(axios.spread(function (res1, res2) { 
 ? ?// res1第一個請求的返回的內(nèi)容,res2第二個請求返回的內(nèi)容
 ? ?// 兩個請求都執(zhí)行完成才會執(zhí)行
}));

五、為什么要封裝

axios 的 API 很友好,你完全可以很輕松地在項目中直接使用。

不過隨著項目規(guī)模增大,如果每發(fā)起一次HTTP請求,就要把這些比如設置超時時間、設置請求頭、根據(jù)項目環(huán)境判斷使用哪個請求地址、錯誤處理等等操作,都需要寫一遍

這種重復勞動不僅浪費時間,而且讓代碼變得冗余不堪,難以維護。為了提高我們的代碼質(zhì)量,我們應該在項目中二次封裝一下 axios 再使用

舉個例子:

axios('http://localhost:3000/data', {
 ?// 配置代碼
 ?method: 'GET',
 ?timeout: 1000,
 ?withCredentials: true,
 ?headers: {
 ? ?'Content-Type': 'application/json',
 ? ?Authorization: 'xxx',
  },
 ?transformRequest: [function (data, headers) {
 ? ?return data;
  }],
 ?// 其他請求配置...
})
.then((data) => {
 ?// todo: 真正業(yè)務邏輯代碼
 ?console.log(data);
}, (err) => {
 ?// 錯誤處理代碼 ?
 ?if (err.response.status === 401) {
 ?// handle authorization error
  }
 ?if (err.response.status === 403) {
 ?// handle server forbidden error
  }
 ?// 其他錯誤處理.....
 ?console.log(err);
});

如果每個頁面都發(fā)送類似的請求,都要寫一堆的配置與錯誤處理,就顯得過于繁瑣了

這時候我們就需要對axios進行二次封裝,讓使用更為便利

六、如何封裝

封裝的同時,你需要和 后端協(xié)商好一些約定,請求頭,狀態(tài)碼,請求超時時間.......

設置接口請求前綴:根據(jù)開發(fā)、測試、生產(chǎn)環(huán)境的不同,前綴需要加以區(qū)分

請求頭 : 來實現(xiàn)一些具體的業(yè)務,必須攜帶一些參數(shù)才可以請求(例如:會員業(yè)務)

狀態(tài)碼: 根據(jù)接口返回的不同status , 來執(zhí)行不同的業(yè)務,這塊需要和后端約定好

請求方法:根據(jù)getpost等方法進行一個再次封裝,使用起來更為方便

請求攔截器: 根據(jù)請求的請求頭設定,來決定哪些請求可以訪問

響應攔截器: 這塊就是根據(jù) 后端`返回來的狀態(tài)碼判定執(zhí)行不同業(yè)務

設置接口請求前綴

利用node環(huán)境變量來作判斷,用來區(qū)分開發(fā)、測試、生產(chǎn)環(huán)境

if (process.env.NODE_ENV === 'development') {
 ?axios.defaults.baseURL = 'http://dev.xxx.com'
} else if (process.env.NODE_ENV === 'production') {
 ?axios.defaults.baseURL = 'http://prod.xxx.com'
}

在本地調(diào)試的時候,還需要在vue.config.js文件中配置devServer實現(xiàn)代理轉(zhuǎn)發(fā),從而實現(xiàn)跨域

devServer: {
 ? ?proxy: {
 ? ? ?'/proxyApi': {
 ? ? ? ?target: 'http://dev.xxx.com',
 ? ? ? ?changeOrigin: true,
 ? ? ? ?pathRewrite: {
 ? ? ? ? ?'/proxyApi': ''
 ? ? ?  }
 ? ?  }
 ?  }
  }

設置請求頭與超時時間

大部分情況下,請求頭都是固定的,只有少部分情況下,會需要一些特殊的請求頭,這里將普適性的請求頭作為基礎配置。當需要特殊請求頭時,將特殊請求頭作為參數(shù)傳入,覆蓋基礎配置

const service = axios.create({
 ? ?...
 ? ?timeout: 30000, ?// 請求 30s 超時
     ?headers: {
 ? ? ? ?get: {
 ? ? ? ? ?'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
 ? ? ? ? ?// 在開發(fā)中,一般還需要單點登錄或者其他功能的通用請求頭,可以一并配置進來
 ? ? ?  },
 ? ? ? ?post: {
 ? ? ? ? ?'Content-Type': 'application/json;charset=utf-8'
 ? ? ? ? ?// 在開發(fā)中,一般還需要單點登錄或者其他功能的通用請求頭,可以一并配置進來
 ? ? ?  }
  },
})

封裝請求方法

先引入封裝好的方法,在要調(diào)用的接口重新封裝成一個方法暴露出去

// get 請求
export function httpGet({
  url,
  params = {}
}) {
  return new Promise((resolve, reject) => {
    axios.get(url, {
      params
    }).then((res) => {
      resolve(res.data)
    }).catch(err => {
      reject(err)
    })
  })
}

// post
// post請求
export function httpPost({
  url,
  data = {},
  params = {}
}) {
  return new Promise((resolve, reject) => {
    axios({
      url,
      method: 'post',
      transformRequest: [function (data) {
        let ret = ''
        for (let it in data) {
          ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&'
        }
        return ret
      }],
      // 發(fā)送的數(shù)據(jù)
      data,
      // url參數(shù)
      params

    }).then(res => {
      resolve(res.data)
    })
  })
}

把封裝的方法放在一個api.js文件中

import { httpGet, httpPost } from './http'
export const getorglist = (params = {}) => httpGet({ url: 'apps/api/org/list', params })

頁面中就能直接調(diào)用

// .vue
import { getorglist } from '@/assets/js/api'

getorglist({ id: 200 }).then(res => {
  console.log(res)
})

這樣可以把api統(tǒng)一管理起來,以后維護修改只需要在api.js文件操作即可

請求攔截器

請求攔截器可以在每個請求里加上token,做了統(tǒng)一處理后維護起來也方便

// 請求攔截器
axios.interceptors.request.use(
  config => {
    // 每次發(fā)送請求之前判斷是否存在token
    // 如果存在,則統(tǒng)一在http請求的header都加上token,這樣后臺根據(jù)token判斷你的登錄情況,此處token一般是用戶完成登錄后儲存到localstorage里的
    token && (config.headers.Authorization = token)
    return config
  },
  error => {
    return Promise.error(error)
  })

響應攔截器

響應攔截器可以在接收到響應后先做一層操作,如根據(jù)狀態(tài)碼判斷登錄狀態(tài)、授權文章來源地址http://www.zghlxwxcb.cn/news/detail-820132.html

// 響應攔截器
axios.interceptors.response.use(response => {
  // 如果返回的狀態(tài)碼為200,說明接口請求成功,可以正常拿到數(shù)據(jù)
  // 否則的話拋出錯誤
  if (response.status === 200) {
    if (response.data.code === 511) {
      // 未授權調(diào)取授權接口
    } else if (response.data.code === 510) {
      // 未登錄跳轉(zhuǎn)登錄頁
    } else {
      return Promise.resolve(response)
    }
  } else {
    return Promise.reject(response)
  }
}, error => {
  // 我們可以在這里對異常狀態(tài)作統(tǒng)一處理
  if (error.response.status) {
    // 處理請求失敗的情況
    // 對不同返回碼對相應處理
    return Promise.reject(error.response)
  }
})

到了這里,關于vue中axios的介紹及封裝(看這一篇就夠了!)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • CSS基礎——看這一篇就夠了

    CSS基礎——看這一篇就夠了

    目錄 一、CSS簡介 1.CSS是什么? 2.CSS的作用 3.CSS的構成 二、CSS選擇器 1.基礎選擇器 (1).標簽選擇器 (2)類選擇器 (3)標簽選擇器 (4) 通配符選擇器 2.復合選擇器 (1)后代選擇器(包含選擇器) (2)子選擇器 (3)并集選擇器 (4)偽類選擇器 ?三、基本屬性 1.字體屬性

    2024年02月09日
    瀏覽(98)
  • 精通線程池,看這一篇就夠了

    精通線程池,看這一篇就夠了

    當我們運用多線程技術處理任務時,需要不斷通過new的方式創(chuàng)建線程,這樣頻繁創(chuàng)建和銷毀線程,會造成cpu消耗過多。那么有沒有什么辦法 避免頻繁創(chuàng)建線程 呢? 當然有,和我們以前學習過多連接池技術類似,線程池通過提前創(chuàng)建好線程保存在線程池中, 在任務要執(zhí)行時取

    2023年04月17日
    瀏覽(97)
  • SourceTree使用看這一篇就夠了

    SourceTree使用看這一篇就夠了

    ?你夢想有一天成為git大師,然而面對復雜的git命令,你感覺TMD這我能記得住嗎?你曾經(jīng)羨慕從命令行敲git命令,才會更加炫酷,然而時間一長,TMD命令我有忘了。那么今天我介紹的這款工具會讓你從git命令中解救出來,這就是git可視化工具SourcTree。 事實上Git的功能十分強大

    2024年02月08日
    瀏覽(24)
  • Docker Volume 看這一篇就夠了

    Docker Volume 看這一篇就夠了

    默認情況下,在容器內(nèi)創(chuàng)建的所有文件都存儲在可寫容器層上。這意味著: 當該容器不再存在時,數(shù)據(jù)不會持續(xù)存在,并且如果另一個進程需要數(shù)據(jù),則可能很難將數(shù)據(jù)從容器中取出。 容器的可寫層與運行容器的主機緊密耦合。您無法輕松地將數(shù)據(jù)移動到其他地方。 寫入容

    2024年02月02日
    瀏覽(107)
  • 還不會二分查找?看這一篇就夠了

    還不會二分查找?看這一篇就夠了

    二分查找分為整數(shù)二分和浮點數(shù)二分,一般所說的二分查找都是指整數(shù)二分。 滿足單調(diào)性的數(shù)組一定可以使用二分查找,但可以使用二分查找的數(shù)組不一定需要滿足單調(diào)性。 不妨假設我們找到了條件 C 1 C_1 C 1 ? ,它和它的 對立條件 C 2 C_2 C 2 ? 能夠?qū)?shù)組 a a a 一分為二,

    2024年01月19日
    瀏覽(27)
  • ElasticSearch常見用法,看這一篇就夠了

    ElasticSearch常見用法,看這一篇就夠了

    2024送書福利正式起航 關注「哪吒編程」,提升Java技能 文末送3本《一本書講透Elasticsearch:原理、進階與工程實踐》 大家好,我是哪吒。 ElasticSearch是一款由Java開發(fā)的開源搜索引擎,它以其出色的實時搜索、穩(wěn)定可靠、快速安裝和方便使用的特性,在Java開發(fā)社區(qū)中贏得了廣

    2024年03月19日
    瀏覽(94)
  • 超圖(HyperGraph)學習,看這一篇就夠了

    超圖(HyperGraph)學習,看這一篇就夠了

    最近事多,好久沒更新了,隨便寫寫(Ctrl+V)點 一、超圖定義 通常圖論中的圖,一條edge只能連接2個vertex,在超圖中,不限量 如何理解呢,就用我正在做的KT問題來看:7道題目-7個頂點;4種概念-4條超邊,其中第1,2,3題都是考察概念1的,則構建一個包含了這仨的超邊,以此類

    2024年02月02日
    瀏覽(27)
  • CAS自旋鎖,看這一篇就夠了

    前序 時隔多年,杰倫終于出了新專輯,《最偉大的作品》讓我們穿越到1920年,見到了馬格利特的綠蘋果、大利的超現(xiàn)實、常玉畫的大腿、莫奈的睡蓮、徐志摩的詩… 他說“最偉大的作品”并不是自己的歌,而是這個世界上最偉大的藝術作品們。 為什么要寫CAS自旋鎖呢?最近

    2023年04月08日
    瀏覽(19)
  • 還不會拓撲排序?看這一篇就夠了

    還不會拓撲排序?看這一篇就夠了

    拓撲排序是一種有向無環(huán)圖(DAG)的頂點排序方法,它將一個有向無環(huán)圖中的所有頂點排成一個線性序列,使得圖中 任意一條有向邊上的起點排在終點的前面 。 這樣說還不夠具體,我們先來看一個例子。假設某大學的課程安排如下: 課程編號 課程名稱 先修課程 1 1 1 高等數(shù)

    2023年04月08日
    瀏覽(74)
  • C++異常處理詳解 看這一篇就夠了

    C++異常處理詳解 看這一篇就夠了

    在程序運行的過程中,我們不可能保證我們的程序百分百不出現(xiàn)異常和錯誤,那么出現(xiàn)異常時該怎么報錯,讓我們知道是哪個地方錯誤了呢? C++中就提供了異常處理的機制。 throw : 當問題出現(xiàn)時,程序會拋出一個異常。這是通過使用 throw 來完成的。 catch : 在您想要處理

    2024年02月14日
    瀏覽(30)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包