TypeScript 作为 JavaScript 语言的超集,它为 JavaScript 添加了可选择的类型标注,大大增强了代码的可读性和可维护性。同时,它提供最新和不断发展的 JavaScript 特性,能让我们建立更健壮的组件。
本篇文章主要介绍基于TypeScript从零重构axios
- 处理请求 url 参数
axios({
method: 'get',
url: '/base/get',
params: {
a: 1,
b: 2
}
})
首先我们来分析一下怎么将多种类型的params拼接在url中。
(1)参数值为数组
最终请求的url
是 /base/get?foo[]=bar&foo[]=baz
(2)参数值为对象
最终请求的 url 是 /base/get?foo=%7B%22bar%22:%22baz%22%7D
,foo 后面拼接的是 {"bar":"baz"} encode
后的结果。
(3)参数值为 Date 类型
最终请求的 url
是 /base/get?date=2019-04-01T05:55:39.030Z
,date
后面拼接的是 date.toISOString()
的结果。
(4)特殊字符支持
对于字符 @
、:
、$
、,
、、[
、]
,我们是允许出现在 url
中的,不希望被 encode。
最终请求的 url
是 /base/get?foo=@:$+
,注意,我们会把空格 转换成 +
。
(5)空值忽略
对于值为 null
或者 undefined
的属性,我们是不会添加到 url 参数中的。
最终请求的 url
是 /base/get?foo=bar
。
(6)丢弃 url 中的哈希标记
最终请求的 url
是 /base/get?foo=bar
(7)保留 url 中已存在的参数
最终请求的 url
是 /base/get?foo=bar&bar=baz
(8)函数实现
helpers/url.ts:
import { isDate, isObject } from './util'
function encode (val: string): string {
return encodeURIComponent(val)
.replace(/%40/g, '@')
.replace(/%3A/gi, ':')
.replace(/%24/g, '$')
.replace(/%2C/gi, ',')
.replace(/%20/g, '+')
.replace(/%5B/gi, '[')
.replace(/%5D/gi, ']')
}
export function bulidURL (url: string, params?: any) {
if (!params) {
return url
}
const parts: string[] = []
Object.keys(params).forEach((key) => {
let val = params[key]
if (val === null || typeof val === 'undefined') {
return
}
let values: string[]
if (Array.isArray(val)) {
values = val
key += '[]'
} else {
values = [val]
}
values.forEach((val) => {
if (isDate(val)) {
val = val.toISOString()
} else if (isObject(val)) {
val = JSON.stringify(val)
}
parts.push(`${encode(key)}=${encode(val)}`)
})
})
let serializedParams = parts.join('&')
if (serializedParams) {
const markIndex = url.indexOf('#')
if (markIndex !== -1) {
url = url.slice(0, markIndex)
}
url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams
}
return url
}
helpers/util.ts:
const toString = Object.prototype.toString
export function isDate (val: any): val is Date {
return toString.call(val) === '[object Date]'
}
export function isObject (val: any): val is Object {
return val !== null && typeof val === 'object'
}
实现 url 参数处理逻辑
我们已经实现了 buildURL 函数,接下来我们来利用它实现 url 参数的处理逻辑。
在 index.ts 文件中添加如下代码:
function axios (config: AxiosRequestConfig): void {
processConfig(config)
xhr(config)
}
function processConfig (config: AxiosRequestConfig): void {
config.url = transformUrl(config)
}
function transformUrl (config: AxiosRequestConfig): string {
const { url, params } = config
return bulidURL(url, params)
}
在执行 xhr 函数前,我们先执行 processConfig 方法,对 config 中的数据做处理,除了对 url 和 params 处理之外,未来还会处理其它属性。
在 processConfig 函数内部,我们通过执行 transformUrl 函数修改了 config.url,该函数内部调用了 buildURL。