手写Axios源码——(一)
Axios (一)axios应该是目前最为常用的前端ajax请求框架, 此次将分四天实现手写Axios源码第一天: 实现基础极简版axios创建基础类型: types.ts文件:// 定义请求方法的类型export type Methods = 'GET' | 'POST' | 'get' | 'post' | 'put' | 'PUT' | 'delete' | 'DELETE' | 'opti
·
Axios (一)
axios应该是目前最为常用的前端ajax请求框架, 此次将分四天实现手写Axios源码
- 第一天: 实现基础极简版axios
- 创建基础类型: types.ts文件:
// 定义请求方法的类型
export type Methods = 'GET' | 'POST' | 'get' | 'post' | 'put' | 'PUT' | 'delete' | 'DELETE' | 'options' | 'OPTIONS'
// 定义axios请求的配置类型,及 axios({})方法中的配置对象类型
// 这里只定义三个基础的配置参数,仅支持get请求的配置
export interface AxiosRequestConfig {
url: string;
method: Methods;
params: any;
}
// axios请求实例的类型, 及就是导出的axios instance的类型
// Promise的泛型T代表Promise编成成功太之后resolve的值的类型
export interface AxiosInstance {
<T = any>(config: AxiosRequestConfig): Promise<T>
}
// axios请求成功后响应的类型
// 泛型T代表响应体的类型
export interface AxiosResponse<T = any> {
data: T;
status: number;
statusText: string;
headers?: Record<string, any>;
config?: AxiosRequestConfig,
request?: XMLHttpRequest
}
- 定义axios入口文件: index.ts, 定义基础的createInstance方法创建axios实例:
// 这里引入Axios类,将会在之后进行定义
import Axios from "./Axios"
import { AxiosInstance } from "./types"
// 用于创建一个axios实例
function createInstance() : AxiosInstance {
let context: Axios = new Axios(); // 之后绑定this指针的上下文
// 让request方法里的this永远指向context, 也就是new Axios()的实例
let instance = Axios.prototype.request.bind(context)
// 把Axios类的实例和类的原型上的方法都拷贝到instance上,也就是request方法上
instance = Object.assign(instance, Axios.prototype, context);
return instance as AxiosInstance;
}
// 这里获取到的axios实例就是在createInstance方法中创建的instance实例,类型为AxiosInstance
let axios = createInstance();
export default axios;
// 同时从入口文件导出axios中的类型定义
export * from "./types"
- 定义axios类文件: Axios.ts,主要实现request方法
import { AxiosRequestConfig, AxiosResponse } from "./types"
// qs库的作用类似于querystring库,将query参数进行转化
import qs from "qs";
// parseHeader库的作用是将http请求返回的header字符串转化为对象
import parseHeader from "parse-headers";
export default class Axios {
// 泛型T用来限制响应对象里的response里的data的类型
request<T>(config: AxiosRequestConfig): Promise<AxiosResponse<T>> {
return this.dispatchRequest(config)
}
// 定义一个派发请求的方法a
dispatchRequest<T>(config: AxiosRequestConfig): Promise<AxiosResponse<T>> {
return new Promise<AxiosResponse<T>>(function (resolve, reject) {
let { method, url, params } = config;
let request = new XMLHttpRequest(); // 创建xhr对象
if (params && typeof params === 'object') {
// 如果params有值并且是一个对象的话,需要拼接成一个字符串放到url后面
// 转化的形式: {name: "chensir", age: 20} => name=chensir&age=20
params = qs.stringify(params);
}
url += ((url.indexOf('?') > 0 ? '&' : '?') + params); // 将params参数拼接到url后面
request.open(method, url, true);
request.responseType = "json"; // 设定请求返回的数据类型json类型
request.onreadystatechange = function () {
// 指定状态变更监听函数
if (request.readyState === 4) {
if (request.status >= 200 && request.status < 300) {
// 请求成功,构建返回的AxiosResponse响应对象
let response: AxiosResponse<T> = {
data: request.response ? request.response : request.responseText,
status: request.status,
statusText: request.statusText,
headers: parseHeader(request.getAllResponseHeaders()),
config,
request
}
resolve(response)
} else {
reject("请求失败")
}
}
}
request.send();
})
}
}
此部分仅仅实现了axios最简单的get请求操作,许多内容会在之后进行改进…
更多推荐
已为社区贡献1条内容
所有评论(0)