axios學(xué)習(xí)歷程(遇到問(wèn)題持續(xù)更新)

  1. axios的作用
  2. axios配置文件
  3. axios在使用中的一些坑

作用

axios其實(shí)就是vue-resourece的一個(gè)更優(yōu)的基于Promise的解決方案临燃,加上vue-resourece早已停止更新睛驳,fetch在配置中又十分的繁瑣烙心,這無(wú)疑讓axios成為我的首選。

配置文件的說(shuō)明

官方文檔其實(shí)已經(jīng)說(shuō)明的很清楚了乏沸,在這里記錄一下淫茵,便于斷網(wǎng)的時(shí)候查詢。

{
  // `url` 是用于請(qǐng)求的服務(wù)器 URL
  url: '/user',

  // `method` 是創(chuàng)建請(qǐng)求時(shí)使用的方法
  method: 'get', // 默認(rèn)是 get

  // `baseURL` 將自動(dòng)加在 `url` 前面蹬跃,除非 `url` 是一個(gè)絕對(duì) URL匙瘪。
  // 它可以通過(guò)設(shè)置一個(gè) `baseURL` 便于為 axios 實(shí)例的方法傳遞相對(duì) URL
  baseURL: 'https://some-domain.com/api/',

  // `transformRequest` 允許在向服務(wù)器發(fā)送前,修改請(qǐng)求數(shù)據(jù)
  // 只能用在 'PUT', 'POST' 和 'PATCH' 這幾個(gè)請(qǐng)求方法
  // 后面數(shù)組中的函數(shù)必須返回一個(gè)字符串蝶缀,或 ArrayBuffer丹喻,或 Stream
  transformRequest: [function (data) {
    // 對(duì) data 進(jìn)行任意轉(zhuǎn)換處理

    return data;
  }],

  // `transformResponse` 在傳遞給 then/catch 前,允許修改響應(yīng)數(shù)據(jù)
  transformResponse: [function (data) {
    // 對(duì) data 進(jìn)行任意轉(zhuǎn)換處理

    return data;
  }],

  // `headers` 是即將被發(fā)送的自定義請(qǐng)求頭
  headers: {'X-Requested-With': 'XMLHttpRequest'},

  // `params` 是即將與請(qǐng)求一起發(fā)送的 URL 參數(shù)
  // 必須是一個(gè)無(wú)格式對(duì)象(plain object)或 URLSearchParams 對(duì)象
  params: {
    ID: 12345
  },

  // `paramsSerializer` 是一個(gè)負(fù)責(zé) `params` 序列化的函數(shù)
  // (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
  paramsSerializer: function(params) {
    return Qs.stringify(params, {arrayFormat: 'brackets'})
  },

  // `data` 是作為請(qǐng)求主體被發(fā)送的數(shù)據(jù)
  // 只適用于這些請(qǐng)求方法 'PUT', 'POST', 和 'PATCH'
  // 在沒(méi)有設(shè)置 `transformRequest` 時(shí)翁都,必須是以下類(lèi)型之一:
  // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
  // - 瀏覽器專(zhuān)屬:FormData, File, Blob
  // - Node 專(zhuān)屬: Stream
  data: {
    firstName: 'Fred'
  },

  // `timeout` 指定請(qǐng)求超時(shí)的毫秒數(shù)(0 表示無(wú)超時(shí)時(shí)間)
  // 如果請(qǐng)求話費(fèi)了超過(guò) `timeout` 的時(shí)間碍论,請(qǐng)求將被中斷
  timeout: 1000,

  // `withCredentials` 表示跨域請(qǐng)求時(shí)是否需要使用憑證
  withCredentials: false, // 默認(rèn)的

  // `adapter` 允許自定義處理請(qǐng)求,以使測(cè)試更輕松
  // 返回一個(gè) promise 并應(yīng)用一個(gè)有效的響應(yīng) (查閱 [response docs](#response-api)).
  adapter: function (config) {
    /* ... */
  },

  // `auth` 表示應(yīng)該使用 HTTP 基礎(chǔ)驗(yàn)證柄慰,并提供憑據(jù)
  // 這將設(shè)置一個(gè) `Authorization` 頭鳍悠,覆寫(xiě)掉現(xiàn)有的任意使用 `headers` 設(shè)置的自定義 `Authorization`頭
  auth: {
    username: 'janedoe',
    password: 's00pers3cret'
  },

  // `responseType` 表示服務(wù)器響應(yīng)的數(shù)據(jù)類(lèi)型税娜,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
  responseType: 'json', // 默認(rèn)的

  // `xsrfCookieName` 是用作 xsrf token 的值的cookie的名稱
  xsrfCookieName: 'XSRF-TOKEN', // default

  // `xsrfHeaderName` 是承載 xsrf token 的值的 HTTP 頭的名稱
  xsrfHeaderName: 'X-XSRF-TOKEN', // 默認(rèn)的

  // `onUploadProgress` 允許為上傳處理進(jìn)度事件
  onUploadProgress: function (progressEvent) {
    // 對(duì)原生進(jìn)度事件的處理
  },

  // `onDownloadProgress` 允許為下載處理進(jìn)度事件
  onDownloadProgress: function (progressEvent) {
    // 對(duì)原生進(jìn)度事件的處理
  },

  // `maxContentLength` 定義允許的響應(yīng)內(nèi)容的最大尺寸
  maxContentLength: 2000,

  // `validateStatus` 定義對(duì)于給定的HTTP 響應(yīng)狀態(tài)碼是 resolve 或 reject  promise 。如果 `validateStatus` 返回 `true` (或者設(shè)置為 `null` 或 `undefined`)藏研,promise 將被 resolve; 否則敬矩,promise 將被 rejecte
  validateStatus: function (status) {
    return status >= 200 && status < 300; // 默認(rèn)的
  },

  // `maxRedirects` 定義在 node.js 中 follow 的最大重定向數(shù)目
  // 如果設(shè)置為0,將不會(huì) follow 任何重定向
  maxRedirects: 5, // 默認(rèn)的

  // `httpAgent` 和 `httpsAgent` 分別在 node.js 中用于定義在執(zhí)行 http 和 https 時(shí)使用的自定義代理蠢挡。允許像這樣配置選項(xiàng):
  // `keepAlive` 默認(rèn)沒(méi)有啟用
  httpAgent: new http.Agent({ keepAlive: true }),
  httpsAgent: new https.Agent({ keepAlive: true }),

  // 'proxy' 定義代理服務(wù)器的主機(jī)名稱和端口
  // `auth` 表示 HTTP 基礎(chǔ)驗(yàn)證應(yīng)當(dāng)用于連接代理弧岳,并提供憑據(jù)
  // 這將會(huì)設(shè)置一個(gè) `Proxy-Authorization` 頭,覆寫(xiě)掉已有的通過(guò)使用 `header` 設(shè)置的自定義 `Proxy-Authorization` 頭业踏。
  proxy: {
    host: '127.0.0.1',
    port: 9000,
    auth: : {
      username: 'mikeymike',
      password: 'rapunz3l'
    }
  },

  // `cancelToken` 指定用于取消請(qǐng)求的 cancel token
  // (查看后面的 Cancellation 這節(jié)了解更多)
  cancelToken: new CancelToken(function (cancel) {
  })
}
// 響應(yīng)結(jié)構(gòu)
// 某個(gè)請(qǐng)求的響應(yīng)包含以下信息

{
  // `data` 由服務(wù)器提供的響應(yīng)
  data: {},

  // `status` 來(lái)自服務(wù)器響應(yīng)的 HTTP 狀態(tài)碼
  status: 200,

  // `statusText` 來(lái)自服務(wù)器響應(yīng)的 HTTP 狀態(tài)信息
  statusText: 'OK',

  // `headers` 服務(wù)器響應(yīng)的頭
  headers: {},

  // `config` 是為請(qǐng)求提供的配置信息
  config: {}
}

其實(shí)這里的話是要 axios(config) 這樣里面去的想一想這么多的配置文件要一股腦都塞進(jìn)去缩筛,確實(shí)看起來(lái)是非常的不雅而且整個(gè)主代碼會(huì)變得亂七八糟,沒(méi)錯(cuò)堡称,剛開(kāi)始學(xué)習(xí)的我真的這樣做了瞎抛,后期幾乎是完全沒(méi)法維護(hù)的,后來(lái)我通過(guò)學(xué)習(xí)花褲衩大大的代碼却紧,才知道桐臊,這些東西是可以封裝起來(lái)的,大概分出來(lái)兩個(gè)文件晓殊。

首先是axios的配置文件(需要自己創(chuàng)建哦我個(gè)人是命名為request.js并且丟在src的utils文件夾中自己建的)

import axios from 'axios'
// axios配置信息
axios.defaults.withCredentials = true
const service = axios.create({
  baseURL: process.env.BASE_API, // api 的 前綴url
  timeout: 5000, // 請(qǐng)求超時(shí)
})
// 數(shù)據(jù)發(fā)送前的攔截器
service.interceptors.request.use(
  config => {
    return config
  },
  error => {
    Promise.reject(error)
  }
)
// 數(shù)據(jù)接受時(shí)的攔截器
service.interceptors.response.use((response) => {
  return response
}, (err) => {
  switch (err.response.status) {
    case 500:
      
      break;
    case 429:
      
      break;
    default:
      
  }

})

export default service

  1. 首先是這個(gè)配置文件断凶,在axios.create這個(gè)方法中,有baseURL和timeout這兩個(gè)配置巫俺,前者指向的是webpack的開(kāi)發(fā)環(huán)境和生產(chǎn)環(huán)境认烁,這個(gè)如果有自己配置的話,就在里面加一個(gè)baseURL即可介汹,如果還不清楚的話却嗡,建議通過(guò)console來(lái)查看具體位置;再下面就是有兩個(gè)攔截器嘹承,一個(gè)是數(shù)據(jù)發(fā)送前窗价,一個(gè)是數(shù)據(jù)接受時(shí),這兩個(gè)攔截器用處很大叹卷,我這么配置之后撼港,基本一目了然,在下面的res攔截器中骤竹,可以捕獲到http錯(cuò)誤碼帝牡,可以通過(guò)判斷和后端的錯(cuò)誤碼來(lái)給予用戶最人性化的提示。
  2. 而在數(shù)據(jù)發(fā)送前的這個(gè)攔截器則可以統(tǒng)一配置 header等這一系列的東西從而避免在主代碼中去重新設(shè)置這些東西蒙揣,比如使用qs去轉(zhuǎn)換需要發(fā)送的數(shù)據(jù)對(duì)吧靶溜,很方便的。

請(qǐng)求地址配置文件(同樣是需要自己創(chuàng)建我個(gè)人是新建了一個(gè)目錄api鸣奔,然后把它放入新加的js文件中)

// 在此處導(dǎo)入之前配置的service
import request from 'request'
export default {
    // 內(nèi)容為請(qǐng)求的函數(shù)墨技,例如:
    post(data) {
    return request({
      url: "",
      method: "post",
      data
    })
  },
    get(params) {
    return request({
      url: "",
      method: "get",
      params
    })
  },
}

這里的請(qǐng)求配置文件就很明了了惩阶,導(dǎo)入之后使用 export default將其中的函數(shù)全部暴露出去方便調(diào)用,而函數(shù)內(nèi)則是這樣的一個(gè)結(jié)構(gòu)扣汪,在函數(shù)內(nèi)部配置一個(gè) url,method,data断楷,為什么要將這些配置分離出來(lái)配置而不是在之前的配置文件中使用,因?yàn)榉?wù)端提供的接口方式多是多樣崭别,可以是get,post,put,dele其中的任意一個(gè)冬筒,而url則是前面相同部分的服務(wù)器地址后面的接口地址那部分,聽(tīng)起來(lái)是不是有點(diǎn)繞茅主?舉個(gè)栗子:現(xiàn)在有兩個(gè)接口舞痰,https://skyserver.com/get_listhttps://skyserver.com/get_list 那么我就可以設(shè)baseURL為 https://skyserver.com,而這里的url則是 /get_list 或者是 /get_list 诀姚,明白了嗎响牛?每一個(gè)接口我們只需要更改后面的接口名和請(qǐng)求方式就好了。

如何去使用赫段?

emm呀打,其實(shí)使用方法有很多,我個(gè)人推薦是去main.js文件中去引入糯笙,例如我引入之后的名字是api那么我就可以使用這行代碼Vue.prototype.$api = api意思為將這個(gè)掛載到vue的原型中去贬丛,這樣的好處就是我們可以直接使用this.$api.get()的方式進(jìn)行調(diào)用,由于axios本身就是一個(gè)基于Promise的項(xiàng)目给涕,其實(shí)就可以直接使用async and await的形式來(lái)進(jìn)行調(diào)用豺憔,借助webpack的一部分功能讓自己的代碼本體變得不再那么冗余。

踩過(guò)的坑

  1. axios本身不會(huì)發(fā)送cookie够庙,需要你自己加上axios.defaults.withCredentials = true這句代碼才會(huì)發(fā)送cookie恭应,但是會(huì)存在跨域問(wèn)題澳厢,在這里由于我只使用了nodejs作為后端所以只舉例nodejs如何解決這個(gè)跨域問(wèn)題的:

首先我使用的是的是express框架茄靠,不過(guò)影響不大,畢竟koa和其他的都是差不多的原理。話不多說(shuō)先上代碼:

// 我們可以直接獲取訪問(wèn)服務(wù)器的來(lái)源直接賦值過(guò)去毅桃,雖然方便,但是要知道本身這個(gè)是防御XSS攻擊准夷,這么設(shè)置之后的風(fēng)險(xiǎn)閱讀者應(yīng)該要須知钥飞。
let origin = req.header.origin
//訪問(wèn)控制允許來(lái)源,有人會(huì)問(wèn)為什么這里不是一個(gè)'*'呢衫嵌,因?yàn)樵趩⒂昧薱ookie之后读宙,是不允許使用通配符的,所以在當(dāng)需要發(fā)送cookie的場(chǎng)景中
res.header('Access-Control-Allow-Origin', origin);
//訪問(wèn)控制允許報(bào)頭 X-Requested-With: xhr請(qǐng)求
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept,X-Token");
//訪問(wèn)控制允許方法
res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
// 它的值是一個(gè)布爾值楔绞,表示是否允許發(fā)送Cookie结闸。默認(rèn)情況下唇兑,Cookie不包括在CORS請(qǐng)求之中。設(shè)為true桦锄,即表示服務(wù)器明確許可扎附,Cookie可以包含在請(qǐng)求中,一起發(fā)給服務(wù)器结耀。這個(gè)值也只能設(shè)為true留夜,如果服務(wù)器不要瀏覽器發(fā)送Cookie,刪除該字段即可图甜。
res.header("Access-Control-Allow-Credentials",true);
//自定義頭信息碍粥,表示服務(wù)端用nodejs,其實(shí)你也可以發(fā)送其他的2333雖然意義不明
res.header('X-Powered-By', 'nodejs');
// 定義發(fā)送的數(shù)據(jù)格式
res.header('Content-Type', 'application/json;charset=utf-8');

這里出現(xiàn)的弊端黑毅,想必一眼就看出來(lái)了對(duì)嗎嚼摩?這里允許了所有來(lái)訪者的url,但是事實(shí)上我們并不能這樣允許矿瘦,因?yàn)檫@樣是有安全問(wèn)題的低斋!so,做個(gè)判斷不就好啦:

// 這里規(guī)定一個(gè)白名單匪凡,允許哪些域名訪問(wèn)膊畴,是一個(gè)數(shù)組
let whitList = ['','']
// 這里則使用的是es6的語(yǔ)法,檢查該變量是否存在于數(shù)組中
// 和es5中的 `indexOf()` 有異曲同工之妙病游,但是它返回的是一個(gè)布爾值唇跨,除了不能夠定位元素的位置,但是用在此處很棒不是么~
if(whitList.includes(origin)){
    // 這里是上面的那段代碼
}

  1. axios是基于es6語(yǔ)法的衬衬,你可能會(huì)遇到 Promise is not function 的問(wèn)題买猖,通常出現(xiàn)在老舊瀏覽器上,可以通過(guò)bable來(lái)進(jìn)行轉(zhuǎn)換滋尉。下圖是其瀏覽器的支持玉控。

Chrome
Firefox
Safari
Opera
Edge
IE
Latest ? Latest ? Latest ? Latest ? Latest ? 11 ?
  1. 它攔截接收?qǐng)?bào)錯(cuò)的信息是在 err.response 中,而不是直接的err就可以獲取到狮惜,這一點(diǎn)是很坑的高诺,一直以來(lái)我都以為是在err中,導(dǎo)致始終無(wú)法捕捉到http狀態(tài)值以及報(bào)錯(cuò)信息碾篡,其實(shí)官方文檔也有說(shuō)明虱而,如果我不是那么的星際也不會(huì)犯這種低級(jí)錯(cuò)誤
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市开泽,隨后出現(xiàn)的幾起案子牡拇,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件惠呼,死亡現(xiàn)場(chǎng)離奇詭異导俘,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)剔蹋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)旅薄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人滩租,你說(shuō)我怎么就攤上這事赋秀。” “怎么了律想?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵猎莲,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我技即,道長(zhǎng)著洼,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任而叼,我火速辦了婚禮身笤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘葵陵。我一直安慰自己液荸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布脱篙。 她就那樣靜靜地躺著娇钱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪绊困。 梳的紋絲不亂的頭發(fā)上文搂,一...
    開(kāi)封第一講書(shū)人閱讀 49,036評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音秤朗,去河邊找鬼煤蹭。 笑死,一個(gè)胖子當(dāng)著我的面吹牛取视,可吹牛的內(nèi)容都是我干的硝皂。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼贫途,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼吧彪!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起丢早,我...
    開(kāi)封第一講書(shū)人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后怨酝,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體傀缩,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年农猬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了赡艰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡斤葱,死狀恐怖慷垮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情揍堕,我是刑警寧澤料身,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站衩茸,受9級(jí)特大地震影響芹血,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜楞慈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一幔烛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧囊蓝,春花似錦饿悬、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至俯萎,卻和暖如春傲宜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背夫啊。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工函卒, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人撇眯。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓报嵌,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親熊榛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子锚国,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345