您现在的位置是:首页 >其他 >手写axios源码系列三:dispatchRequest发送请求网站首页其他

手写axios源码系列三:dispatchRequest发送请求

斯图尔te 2023-06-06 16:00:02
简介手写axios源码系列三:dispatchRequest发送请求

在这里插入图片描述
上篇文章中介绍了创建 axios 函数对象的思路,在 Axios 的原型对象上声明了一个 request 方法,在 request 方法中调用了 dispatchRequest 用来发送请求。

现在,让我们来看看 dispatchRequest 发送请求的代码设计思路。

一、dispatchRequest 发送请求代码设计思路

1、创建 dispatchRequest.js 文件

import adapters from "./adapters.js";
import defaults from "./defaults.js";  // {adapter:["xhr","http"]}

export default function dispatchRequest(config){
	// 使用 adapters.getAdapter() 获取发送请求的方式 xhr或者 http
	const adapter = adapters.getAdapter(config.adapter || defaults.adapter);
	// 返回一个新的 promise对象
	return adapter(config).then(response => {
		// 返回响应数据
		return response;
	}, error => {
		throw new Error(error);
	})
}

2、创建 adapters.js 文件

import xhrAdapter from "./xhr.js";
// import httpAdapter from "./http.js";  // http为 nodejs支持发送的方式,此处不做讨论

// 此处维护一个已知适配器对象
const knownAdapters = {
	// http: httpAdapter,
	xhr: xhrAdapter
}
export default const adapters = {
	// 返回一个通信方式适配器
	getAdapter: (adapters) => {
		// 兼容性判断:是否为数组
		adapters = Array.isArray(adapters) ? adapters : [adapters];
		let adapter;
		// 获取 xhr 适配器
		for(let i = 0; i < adapters.length; i++){
			adapter = knownAdapters[adapters[i]];
			break;
		}
		// adapter 应为一个函数,否则抛出错误
		if (typeof adapter !== "function"){ 
			throw new TypeError('adapter is not a function');
		}
		return adapter;
	}
}

3、创建 xhr.js 文件

使用 XMLHttpRequest 创建一个 AJAX 请求函数,因为在 dispatchRequest.js 中使用 promise.then(),所以需要返回一个 promise 对象。

以下是一个创建 AJAX 请求的函数 xhrAdapter

export default function xhrAdapter(config){
	// 返回一个 promise对象
	return new Promise((resolve, reject) => {
		// 创建一个xhr对象
		const request = new XMLHttpRequest();
		// 请求资源的地址以及方法,true为异步方式,也是默认方式,可省略
		request.open(config.url, config.method, true);
		// 判断请求状态
		request.onreadystatechange = function(){
			if (request.readyState === 4){
				if (request.status >= 200 && request.status < 300){
					// 反序列化(将响应数据从字符串转换为对象)
					const responseData = JSON.parse(request.responseText)
					// 结构化最终结果
					const response = {
						data: responseData, 						// 响应体
						status: request.status, 					// 响应状态
						statusText: request.statusText,				// 响应状态描述
						headers: request.getAllResponseHeaders(),	// 响应头
						config,  									// 配置项
						request  									// xhr请求对象
					}
					// 返回最终结果
					resolve(response)
				} else {
					// 响应状态不为 2xx 时,报错
					reject(new Error(`请求失败!状态码为${request.status}`))
				}
			}
		}
		// 发送请求
		request.send(config.data || null);
	})
}

4、总结

dispatchRequest 这里的代码逻辑还是比较简单,比较清晰的。

用一张图来表示可能更直观一些:

在这里插入图片描述

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。