使用Typescript重構axios(二十九)——添加baseURL


0. 系列文章

1.使用Typescript重構axios(一)——寫在最前面
2.使用Typescript重構axios(二)——項目起手,跑通流程
3.使用Typescript重構axios(三)——實現基礎功能:處理get請求url參數
4.使用Typescript重構axios(四)——實現基礎功能:處理post請求參數
5.使用Typescript重構axios(五)——實現基礎功能:處理請求的header
6.使用Typescript重構axios(六)——實現基礎功能:獲取響應數據
7.使用Typescript重構axios(七)——實現基礎功能:處理響應header
8.使用Typescript重構axios(八)——實現基礎功能:處理響應data
9.使用Typescript重構axios(九)——異常處理:基礎版
10.使用Typescript重構axios(十)——異常處理:增強版
11.使用Typescript重構axios(十一)——接口擴展
12.使用Typescript重構axios(十二)——增加參數
13.使用Typescript重構axios(十三)——讓響應數據支持泛型
14.使用Typescript重構axios(十四)——實現攔截器
15.使用Typescript重構axios(十五)——默認配置
16.使用Typescript重構axios(十六)——請求和響應數據配置化
17.使用Typescript重構axios(十七)——增加axios.create
18.使用Typescript重構axios(十八)——請求取消功能:總體思路
19.使用Typescript重構axios(十九)——請求取消功能:實現第二種使用方式
20.使用Typescript重構axios(二十)——請求取消功能:實現第一種使用方式
21.使用Typescript重構axios(二十一)——請求取消功能:添加axios.isCancel接口
22.使用Typescript重構axios(二十二)——請求取消功能:收尾
23.使用Typescript重構axios(二十三)——添加withCredentials屬性
24.使用Typescript重構axios(二十四)——防御XSRF攻擊
25.使用Typescript重構axios(二十五)——文件上傳下載進度監控
26.使用Typescript重構axios(二十六)——添加HTTP授權auth屬性
27.使用Typescript重構axios(二十七)——添加請求狀態碼合法性校驗
28.使用Typescript重構axios(二十八)——自定義序列化請求參數
29.使用Typescript重構axios(二十九)——添加baseURL
30.使用Typescript重構axios(三十)——添加axios.getUri方法
31.使用Typescript重構axios(三十一)——添加axios.all和axios.spread方法
32.使用Typescript重構axios(三十二)——寫在最后面(總結)

項目源碼請猛戳這里!!!

1. 前言

在實際工作項目中,服務端所有的api接口都會部署在同一個域名下,例如豆瓣電影的api接口都統一部署在https://api.douban.com下面,當我們想要獲取正在熱映的電影列表時可以請求https://api.douban.com/v2/movie/in_theaters;當想要獲取TOP250電影列表時可以請求https://api.douban.com/v2/movie/top250等等。細心的你肯定會看到每個電影接口的前綴https://api.douban.com/v2/movie/都是相同的,只是后面的類別不同。本着能少些一行代碼就少一寫一行的原則,有沒有什么辦法只需把前綴寫一次,每次請求的時候只用帶上后面的類別后綴即可。答案當然是有的。

官方axios在請求配置對象中為我們提供了baseURL屬性,官方文檔對該屬性介紹如下:

// `baseURL` will be prepended to `url` unless `url` is absolute.
// It can be convenient to set `baseURL` for an instance of axios to pass relative URLs
// to methods of that instance.
baseURL: 'https://some-domain.com/api/',

當配置了baseURL屬性,它就會和之后請求傳入的 url 拼接成完整的絕對地址,除非請求傳入的 url 已經是絕對地址。為axios實例設置baseURL可以方便地將相對url傳遞給該實例的方法。

說了這么多,其實就是想表達如下意思:

const instance = axios.create({
  baseURL: 'https://api.douban.com/v2/movie/'
})

instance.get('/in_theaters')  // 獲取正在熱映的電影列表

instance.post('/top250')   // 獲取`TOP250`電影列表

那么接下來,我們就為我們的axios添加baseURL屬性以及相關功能。

2. 思路分析

實現之前,我們先來理一下思路:

官方文檔說:當配置了baseURL屬性,它就會和之后請求傳入的 url 拼接成完整的絕對地址,除非請求傳入的 url 已經是絕對地址。

那么當用戶配置了baseURL屬性時:

  • 首先,判斷傳入的url是否是絕對地址,如果是,則不用和baseURL拼接;
  • 如果不是,則將baseURL與傳入的url進行拼接;
  • 拼接好之后,將拼接后的url作為請求真正的url發送請求;

OK,以上就是實現思路,接下來,我們就逐步實現它。

3. 向請求配置對象添加屬性

向請求配置對象config中添加 baseURL 屬性之前,我們需要先在src/types/index.ts中的配置對象的接口類型定義AxiosRequestConfig上添加該屬性的定義,如下:

export interface AxiosRequestConfig {
  // 新增
  baseURL?: string;
}

4. 判斷傳入的url是否為絕對地址

首先,我們先來編寫一個輔助函數 isAbsoluteURL,用來判斷傳入的url是否為絕對地址,我們在src/helpers目錄下創建isAbsoluteURL.ts文件,在該文件中編寫該函數,如下:

export default function isAbsoluteURL(url: string): boolean {
  // 如果URL以“<scheme>://”或“//”(協議相對URL)開頭,則該URL被視為絕對值。
  // RFC 3986將方案名稱定義為以字母開頭的字符序列,
  // 后跟字母,數字,加號,句點或連字符的任意組合。
  return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url);
}

該函數很簡單,就是編寫一個絕對地址的正則表達式,如果傳入的url匹配該正則,則表明它是絕對地址,反之則不是。

5. 拼接url

如果傳入的url不是絕對地址的話,我們就需要將baseURL與傳入的url進行拼接,所以我們再編寫一個拼接的輔助函數combineURLs,該函數用來將baseURL與傳入的url進行拼接,將拼接后的結果返回。我們在src/helpers目錄下創建combineURLs.ts文件,在該文件中編寫該函數,如下:

export default function combineURLs(
  baseURL: string,
  relativeURL?: string
): string {
  return relativeURL
    ? baseURL.replace(/\/+$/, "") + "/" + relativeURL.replace(/^\/+/, "")
    : baseURL;
}

在該函數中,為了統一起見,無論baseURL最后有沒有/,都將其去掉,並且不管傳入的url前面有沒有/,也都將其去掉,最后用/將兩部分連接。

OK,所有的輔助函數都實現好之后,我們就要在src/core/dispatchRequest.ts文件中的transformUrl函數中編寫相關邏輯使用這兩個輔助函數。

6. 修改transformUrl函數邏輯

按照第2章的思路分析,先判斷傳入的url是否是絕對地址,如果不是,則將baseURL與傳入的url進行拼接;拼接好之后,將拼接后的url作為請求真正的url發送請求;如下:

function transformUrl(config: AxiosRequestConfig): string {
  let { url, params, paramsSerializer, baseURL } = config;
  if (baseURL && !isAbsoluteURL(url!)) {
    url = combineURLs(baseURL, url);
  }
  return bulidURL(url!, params, paramsSerializer);
}

OK,baseURL 屬性以及相關邏輯就處理好了,接下來,我們就編寫demo來測試下效果如何。

7. demo編寫

examples 目錄下創建 baseURL目錄,在 baseURL目錄下創建 index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>baseURL demo</title>
  </head>
  <body>
    <script src="/__build__/baseURL.js"></script>
  </body>
</html>

接着再創建 app.ts 作為入口文件:

import axios from "../../src/axios";

const instance = axios.create({
  baseURL: 'http://192.168.1.106:3000/'
})

instance.get('/api/baseURL')

instance.get('http://192.168.1.106:3000/api/baseURL')

在本demo中,我們編寫了兩個請求,第一個請求用的是相對url,它會將baseURL與其拼接;而第二個請求時絕對url,不會再去拼接 baseURL

接着在 server/server.js 添加新的接口路由:

// 添加baseURL屬性
router.get("/api/baseURL", function(req, res) {
  res.end();
});

最后在根目錄下的index.html中加上啟動該demo的入口:

<li><a href="examples/baseURL">baseURL</a></li>

OK,我們在命令行中執行:

# 同時開啟客戶端和服務端
npm run server | npm start

接着我們打開 chrome 瀏覽器,訪問 http://localhost:8000/ 即可訪問我們的 demo 了,我們點擊 baseURL,就可以看到兩個請求都已經正常發出,並且打開F12中的network可以看到:第一個請求的url是通過baseURL與傳入的url拼接后的結果,而第二個請求的url是原始傳入的url,沒有被拼接。

OK,以上就是為我們的axios添加baseURL屬性,並實現了其功能。

(完)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM