首页/文章/http-网络

axios是怎么做到适配xhr和http的

2024-01-03
8313 分钟
...

前言

我们在使用axios的时候是不需要判断这个环境和指定发送的方法的,但是它既可以发送浏览器环境下xhr请求,也可以发送node环境下http请求,就来看一下这是怎么实现的。

基础结构

——lib 
|——adpters 
    |—— adapters.js 
    |—— http.js 
    |—— xhr.js 
|——cancel 
    |——CanceledError.js 
    |——CancelToken.js 
    |——isCancel.js 
|——core 
    |——Axios.js 
    |——AxiosError.js 
    |——AxiosHeader.js 
    |——buildFullpath.js 
    |——despatchRequest.js 
    |——InterceptorManager.js 
    |——mergeConfig.js 
    |——settle.js 
    |——transformData.js 
    |——defaults 
    |——index.js 
|——transitional 
|——env 
|——helper 
|——plaform 
|——axios.js 
|——utils.js 

发送请求

通常我们使用axios发送请求使用的方法就是 axios.request(configOrUrl,config) 或者 axios.get(url,config)

axios是Axios的实例,在Axios类中,有一个很重要的方法 request(), 其他的get,post 等方法都是依赖request方法改造来的

首先,我们看一下Axios类中有什么


class Axios {
  constructor(instanceConfig) {
    this.defaults = instanceConfig; 
    this.interceptors = {
      request: new InterceptorManager(), 
      response: new InterceptorManager() 
    };
  }
  
  request(config){
  
      
      promise = dispatchRequest.call(this, newConfig);
  }
  
  getUri(config){}
}

request()是 发送请求的方法,之后get(),post()等方法封装request()并挂载在Axios原型对象中。从而可以通过 axios.get() 来发送请求

request()方法处理请求头,拦截请求,发送请求,拦截响应。我们忽略拦截器,不妨直接看 dispatchRequest()


export default function dispatchRequest(config) {

 const adapter = adapters.getAdapter(config.adapter || defaults.adapter);

  return adapter(config).then(function onAdapterResolution(response) {
      
  }
}

dispatchRequest() 转换请求数据、 选择adapter并发送请求、 转换响应数据。

这个adapter是什么呢?

适配器。发送数据有多种环境,我们常用的就是node环境和浏览器环境,但是我们在使用axios时是不用区分是何种环境的,原因就在于axios做了适配。

通过adapters.getAdapter() 得到一个函数,这个函数才是真正发送请求的地方。实际上可以返回的函数有两个

  • httpAdapter
  • xhrAdapter

xhr适配器

const isXHRAdapterSupported = typeof XMLHttpRequest !== 'undefined';


export default isXHRAdapterSupported && function (config) {
  return new Promise(function dispatchXhrRequest(resolve, reject) {
      
      let request = new XMLHttpRequest();
      
      request.open(config.method.toUpperCase(), buildURL(fullPath, config.params, config.paramsSerializer), true);
      function onload(){}
      
      request.send(requestData || null);
  }

http适配器


const isHttpAdapterSupported = typeof process !== 'undefined' && utils.kindOf(process) === 'process';

export default isHttpAdapterSupported && function httpAdapter(config) {
  
  
  return new Promise(async function dispatchHttpRequest(resolvePromise, rejectPromise) {
        
        const options = {...   };
            
         req = transport.request(options, function handleResponse(res){
             
             const response = {...};
         })
         
         if (utils.isStream(data)) {
          data.pipe(req);
         }else {
             req.end()
         }
 }

调用适配器

适配器模式讲究的就是一个兼容,从外部来看我们并不关心它具体是什么请求。具体是怎么实现的呢?

发送请求的大致过程

\\ lib/adapters/adapter
const knownAdapters = {
  http: httpAdapter, 
  xhr: xhrAdapter 
}

\\ lib\core\diaptchRuest
function dispactchRequest(){
    const adapter = adapters.getAdapter(config.adapter || defaults.adapter);
    
    return adpater(config).then(){...} 
}
 

getAdapter() 的具体实现


getAdapter: (adapters) => {

    adapters = utils.isArray(adapters) ? adapters : [adapters];
     for (let i = 0; i < length; i++) {
      nameOrAdapter = adapters[i];
      if (!isResolvedHandle(nameOrAdapter)) {
        adapter = knownAdapters[(id = String(nameOrAdapter)).toLowerCase()];
      }
      if (adapter) {
        break;
       }
    }
}

getAdapter 的实现就是传入适配器列表,找到最先可以执行的适配器,将适配器返回。 默认的适配器列表是 ['xhr','http']从中可以看出xhr的优先级是要比http请求的优先级高的。

总结

  • 无论是xhr适配器还是http适配器,都是一个接收config返回promise的函数,结构上是一致的,因此可以通过适配器模式兼容他们,在使用axios的时候就不用考虑是什么环境。
  • axios通过判断环境和适配器列表选择适配器,发送相应请求。

如果您觉得这篇文章有帮助,请点个赞吧~

分享文章

相关文章

更多文章 →
http-网络2025-10-27
frp-内网穿透详解
1\. 简介与工作原理 frp(Fast Reverse Proxy)是一个高性能的反向代理 / 内网穿透工具。典型部署模式: 在 公网 VPS 上运行 (服务端),监听来自 的 出站持久连接 (控制端口,通常 7000)。 在 内网机器 上运行 (客户端),与 frps 建立长连接并注册若干映射(如 tcp/http)。 当外部请求到达 frps(公网),frps 根据路由规则把流量转发回对应的 frpc 连接,再由 frpc 转发到...
学习
http-网络2025-10-13
内网穿透介绍
&nbsp; 1\. 简要概念与为什么需要内网穿透 大多数家庭/公司网络在私有网(RFC1918)后面,通过 NAT 共享一个公网 IP。NAT 允许内网对外发起连接,但阻止公网主动连入。 内网穿透 就是建立从公网到内网的可达通道,常用于:Webhook 回调、远程演示、远程管理、IoT 设备接入、远程调试等。 2\. 核心原理(三行总结) 反向连接 :内网主动连到公网穿透服务器,建立一条"回路"。 中继/代理 :穿透服务器把外部流量中...
学习
http-网络2025-08-06
按下回车后网页是怎么出来的
当你在浏览器中输入一个网址,比如 ,然后按下回车键,几秒钟后页面就完整地呈现在你眼前。这个看似简单的操作,背后其实是一整套精密协作的网络机制在起作用。本文将带你从基础讲起,理解 Web 开发中最重要的网络知识,帮助你搞清楚: 数据是如何从服务器传到你的电脑,并最终变成网页的? 一、互联网通信的分层模型:OSI 七层模型 为了管理复杂的网络通信,工程师们提出了一个通用的参考模型—— OSI 七层模型 。它把整个通信过程划分为七个层次,每一...
学习面试
http-网络2025-06-20
MQTT与HTTP在物联网中的比较:为什么MQTT是更好的选择
简介: 通过上述分析,可以看出MQTT在物联网应用中的确是更好的选择。其高效的通信模型、低带宽消耗、稳定的连接保持机制以及可靠的消息质量保证,使其在各种物联网场景中都能表现出色。开发者在设计和实现物联网系统时,应优先考虑采用MQTT协议,以充分发挥其在资源受限环境下的优势,提升系统的整体性能和可靠性。 【杂谈】 MQTT与HTTP在物联网中的比较:为什么MQTT是更好的选择 在物联网(IoT)应用中,选择合适的通信协议是实现高效、可靠数...
学习
http-网络2025-03-04
网络代理详解
一、 的基础概念 1\. 什么是代理? 代理是一种通过中间服务器来帮助 访问目标服务器的技术。代理服务器位于客户端与服务器之间,充当两者的中介,从而实现客户端和服务器之间的隔离。用户的所有请求经过代理后,再发往目标服务器,而目标服务器的响应则返回代理,再由代理传递给用户。 2\. 网络代理的工作流程 在基本的网络代理工作流程中, 扮演了“请求转发者”和“响应返回者”的角色: 1. 客户端请求 :客户端将请求发送到代理服务器,而不是直接发...
学习面试
http-网络2024-11-29
没有koa的cors你怎么处理跨域?
关联问题: JSONP有何局限性 CORS如何处理复杂请求 代理在生产环境效果如何 前言 “金九银十”的秋招,就像是落进池塘的羽毛,连点水花都没砸起来。已读不回是常态,能给面试已是情分,能拿offer的更是少之又少。可怜我在寒潮来临的深秋之际,也只得哀叹一句“越来越冷了啊...” 不过人总是要吃饭的,所以再怎么冷,卖炭翁也得卖炭,牛马攻城狮也得“攻城”,既是为了填饱肚子,也是为了“春天”做准备。所以今天为各位前端工程狮细聊一下前端面试中...
学习面试

评论

请登录后发表评论

去登录
加载评论中...

目录