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请求操作,许多内容会在之后进行改进…