手把手帶你使用 typescript 實現一個 axios 庫(一)

Apinkpig發表於2019-05-07

注:本教程基於慕課網黃大神的課程進行的整理

原始碼地址

前言

本人是個工作一年多的前端小菜鳥,熱愛寫程式碼,喜歡分享。近期在學習黃大神的課程,就想著寫部落格來記錄一下,一方面加深自己的理解,一方面分享出來給需要的人

需求分析

我們要做的是用 typescript 來重構 axios,so 你需要先熟悉axios,此次重構,會支援以下功能。

  • 在瀏覽器端使用 XMLHttpRequest 物件通訊
  • 支援 Promise API
  • 支援請求和響應的攔截器
  • 支援請求資料和響應資料的轉換
  • 支援請求的取消
  • JSON 資料的自動轉換
  • 客戶端防止 XSRF

專案初始化

這裡我們使用 typescript 的一個腳手架工具typescript-library-starter,感興趣的可以點選進去進一步學習。

前言

如果你還不瞭解typescript,可以先看一下官網的5分鐘上手TypeScript這篇文章

使用方式

git clone https://github.com/alexjoverm/typescript-library-starter.git ts-axios-pro

cd ts-axios-pro

npm install
// 如果npm安裝慢的話,可以用如下命令替換為國內的淘寶源
npm install --registry=https://registry.npm.taobao.org
複製程式碼

目錄結構

├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── code-of-conduct.md
├── node_modules
├── package-lock.json
├── package.json
├── rollup.config.ts // rollup 配置檔案
├── src // 原始碼目錄
├── test // 測試目錄
├── tools // 釋出到 GitHup pages 以及 釋出到 npm 的一些配置指令碼工具
├── tsconfig.json // TypeScript 編譯配置檔案
└── tslint.json // TypeScript lint 檔案
複製程式碼

基礎請求程式碼的實現

先看一個基礎的請求,我們通過傳入一個物件來傳送請求。

axios({
  method: 'get',
  url: '/simple/get',
  params: {
    a: 1,
    b: 2
  }
})
複製程式碼

建立入口檔案

在src目錄下建立一個index.ts檔案用來作為我們的入口檔案。如果你仔細觀察了上面的axios請求,不難寫出如下的程式碼

function axios(config) {

}

export default axios
複製程式碼

此時,你的編輯器會給你一個紅色的波浪線警告和一個綠色的警告(如果沒有,請安裝TSlint外掛),滑鼠移上去會顯示錯誤資訊。如下圖...

這裡是圖片

移到config上會展示

1、已宣告“config”,但從未讀取其值。ts(6133)
引數“config”隱式具有“any”型別。ts(7006)
2、移到綠色的那裡會告訴你這個函式不能為空
原因:預設在tsconfig.json檔案中吧strict設定為了true(建議開啟,不要吧它設定成false)
複製程式碼

解決方法:給config定義介面型別

建立型別檔案(type)

在src目錄下建立一個types目錄,在下面建立一個index.ts型別定義檔案。
定義一個AxiosRequestConfig介面型別

export interface AxiosRequestConfig {
  url: string   
  method: string
  data?: any  // 可選引數用?號表示
  params?: any
}
複製程式碼

其中urldataparams這三者都是使用者隨機填寫的,但是method是固定為getpostput等。
so我們這裡需要把method的型別改寫為字串字面量型別

接下來我們改寫上面的程式碼如下

export type Method = 'get' | 'GET'
| 'delete' | 'DELETE'
| 'head' | 'HEAD'
| 'options' | 'OPTIONS'
| 'post' | 'POST'
| 'put' | 'PUT'
| 'patch' | 'PATCH'
export interface AxiosRequestConfig {
  url: string
  method: Method
  data?: any
  params?: any
}
複製程式碼

這樣限制了輸入的method只能為指定的字串
scr下的index.ts

import { AxiosRequestConfig } from './types'
function axios(config: AxiosRequestConfig) {
  // aaa
}

export default axios
複製程式碼

此時,就不會有警告資訊

編寫原生ajax請求程式碼

我們利用模組化的思想,將這部分邏輯拆分為一個單獨的ts檔案。在src目錄下新建一個xhr.ts檔案,內容如下

import { AxiosRequestConfig } from './types' // 引入config型別定義

// void: 它表示沒有任何型別。 當一個函式沒有返回值時,你通常會見到其返回值型別是 void:
export default function xhr(config: AxiosRequestConfig): void {
  const { url, method = 'get', data = null } = config // 從config中解構出url,method, data 引數

  // 建立XMLHttpRequest物件
  const request = new XMLHttpRequest()

  /**
   * @description: 傳送
   * @param method {String} 請求方式
   * @param url { String} 請求url
   * @param async {Boolean} 是否非同步
   */
  request.open(method.toUpperCase(), url, true)

  request.send(data)
}
複製程式碼

未完待續...


相關文章