需求
为了用户更加方便地使用axios,我们需要扩展一些方法
- axios.request(config)
- axios.get(url[, config])
- axios.delete(url[, config])
- axios.head(url[, config])
- axios.options(url[, config])
- axios.post(url[, data[, config]])
- axios.put(url[, data[, config]])
- axios.patch(url[, data[, config]])
如果使用了这些方法,我们就不必一定在config中指定url,method,data这些属性了。
从需求上看,axios不单单是一个方法,更像是一个混合对象,本身是一个方法,同时又拥有很多方法属性。接下来我们来实现这个混合对象。
创建Axios接口
interface Axios {
request(config: AxiosRequestConfig): AxiosPromise
get(url: string, config?: AxiosRequestConfig): AxiosPromise
head(url: string, config?: AxiosRequestConfig): AxiosPromise
delete(url: string, config?: AxiosRequestConfig): AxiosPromise
options(url: string, config?: AxiosRequestConfig): AxiosPromise
put(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise
post(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise
patch(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise
}
创建Axios类
src/core/Axios.ts
import { AxiosRequestConfig, AxiosPromise, Method } from "../types";
import dispatchRequest from "./dispatchRequest";
export default class Axios {
request(config: AxiosRequestConfig): AxiosPromise {
return dispatchRequest(config)
}
get(url: string, config?: AxiosRequestConfig): AxiosPromise {
return this._requestMethod(url, 'get', config)
}
delete(url: string, config?: AxiosRequestConfig): AxiosPromise {
// const newConfig = Object.assign(config || {}, {
// url,
// method: 'delete'
// })
// return dispatchRequest(newConfig)
return this._requestMethod(url, 'delete', config)
}
head(url: string, config?: AxiosRequestConfig): AxiosPromise {
return this._requestMethod(url, 'head', config)
}
options(url: string, config?: AxiosRequestConfig): AxiosPromise {
return this._requestMethod(url, 'options', config)
}
put(url: string, data?: any, config?: AxiosRequestConfig,): AxiosPromise {
return this._requestMethod(url, 'put', config, data)
}
post(url: string, data?: any, config?: AxiosRequestConfig,): AxiosPromise {
return this._requestMethod(url, 'post', config, data)
}
patch(url: string, data?: any, config?: AxiosRequestConfig,): AxiosPromise {
return this._requestMethod(url, 'patch', config, data)
}
_requestMethod(url: string, method: Method, config?: AxiosRequestConfig, data?: any) {
const newConfig = Object.assign(config || {}, {
url,
method,
data: data || null
})
return this.request(newConfig)
}
}
src/axios.ts
import Axios from './core/Axios'
const axios = new Axios()
export default axios
但是单单这样做有一个问题,就是axios方法是可以直接像这样使用的:
axios({...config})
但是显然我们上面的实现不能达到这个目的,所以我们需要做进一步的处理。
创建AxiosInstance接口
interface AxiosInstance extends Axios {
(config: AxiosRequestConfig): AxiosPromise
}
AxiosInstance继承Axios接口,那么它就是一个混合接口
src/axios.ts
import { AxiosInstance } from "./types";
import Axios from './core/Axios'
import { extend } from "./helpers/util";
function createInstance() {
const context = new Axios()
const instance = Axios.prototype.request.bind(context)
extend(instance, context)
return instance as AxiosInstance
}
const axios = createInstance()
export default axios
src/healpers/util.ts
function extend<T, U>(to: T, from: U): T & U {
for (const key in from) {
;(to as T & U)[key] = from[key] as any
}
return to as T & U
}
拥有axios方法的instance,也获取到axios的属性方法,这样axios除了可以使用axios.get, axios.put等方法,也可以直接使用axios(config)。
编写demo
import axios from '../../src/index'
axios({
url: '/extend/post',
method: 'post',
data: {
msg: 'hi'
}
})
axios.request({
url: '/extend/post',
method: 'post',
data: {
msg: 'hello'
}
})
axios.get('/extend/get')
axios.options('/extend/options')
axios.delete('/extend/delete')
axios.head('/extend/head')
axios.post('/extend/post', { msg: 'post' })
axios.put('/extend/put', { msg: 'put' })
axios.patch('/extend/patch', { msg: 'patch' })
至此,我们支持了对axios API的扩展,把它变成了一个混合对象。官方的axios实例,除了支持axios(config)外,还支持传入2个参数axios(url, config),这里就涉及到函数重载的概念,接下来我们来实现这个功能。
网友评论