当前位置:首页 > 科技  > 软件

Axios 跨端架构是如何实现的?

来源: 责编: 时间:2024-05-07 09:15:51 257观看
导读我们都知道,axios 是是一个跨平台请求方案,在浏览器端采用 XMLHttpRequest API 进行封装,而在 Node.js 端则采用 http/https 模块进行封装。axios 内部采用适配器模式将二者合二为一,在隐藏了底层的实现的同时,又对外开放

我们都知道,axios 是是一个跨平台请求方案,在浏览器端采用 XMLHttpRequest API 进行封装,而在 Node.js 端则采用 http/https 模块进行封装。axios 内部采用适配器模式将二者合二为一,在隐藏了底层的实现的同时,又对外开放了一套统一的开放接口。HxU28资讯网——每日最新资讯28at.com

那么本文,我们将来探讨这个话题:axios 的跨端架构是如何实现的?HxU28资讯网——每日最新资讯28at.com

从 axios 发送请求说起

我们先来看看 axios 是如何发送请求的。HxU28资讯网——每日最新资讯28at.com

// 发送一个 GET 请求axios({   method: 'get',  url: 'https://jsonplaceholder.typicode.com/comments'  params: { postId: 1 }}) // 发送一个 POST 请求axios({  method: 'post'  url: 'https://jsonplaceholder.typicode.com/posts',  data: {    title: 'foo',    body: 'bar',    userId: 1,  }})

dispatchRequest() 方法

当使用 axios 请求时,实际上内部是由 Axios[3] 实例的 .request() 方法处理的。HxU28资讯网——每日最新资讯28at.com

// /v1.6.8/lib/core/Axios.js#L38async request(configOrUrl, config) {    try {      return await this._request(configOrUrl, config);    } catch (err) {}}

而 ._request() 方法内部会先将  configOrUrl, config 2 个参数处理成 config 参数。HxU28资讯网——每日最新资讯28at.com

// /v1.6.8/lib/core/Axios.js#L62_request(configOrUrl, config) {    if (typeof configOrUrl === 'string') {      config = config || {};      config.url = configOrUrl;    } else {      config = configOrUrl || {};    }    // ...}

这里是为了同时兼容下面 2 种调用方法。HxU28资讯网——每日最新资讯28at.com

// 调用方式一axios('https://jsonplaceholder.typicode.com/posts/1')// 调用方式二axios({  method: 'get',  url: 'https://jsonplaceholder.typicode.com/posts/1'})

当然,这不是重点。在 ._request() 方法内部请求最终会交由 dispatchRequest() 处理。HxU28资讯网——每日最新资讯28at.com

// /v1.6.8/lib/core/Axios.js#L169-L173try {  promise = dispatchRequest.call(this, newConfig);} catch (error) {  return Promise.reject(error);}

dispatchRequest() 是实际调用请求的地方,而实际调用是采用  XMLHttpRequest API(浏览器)还是http/https 模块(Node.js),则需要进一步查看。HxU28资讯网——每日最新资讯28at.com

// /v1.6.8/lib/core/dispatchRequest.js#L34export default function dispatchRequest(config) { /* ... */ }

dispatchRequest() 接收的是上一步合并之后的 config 参数,有了这个参数我们就可以发送请求了。HxU28资讯网——每日最新资讯28at.com

跨端适配实现

// /v1.6.8/lib/core/dispatchRequest.js#L49const adapter = adapters.getAdapter(config.adapter || defaults.adapter);

这里就是我们所说的 axios 内部所使用的适配器模式了。HxU28资讯网——每日最新资讯28at.com

axios 支持从外出传入 adapter 参数支持自定义请求能力的实现,不过很少使用。大部分请求下,我们都是使用内置的适配器实现。HxU28资讯网——每日最新资讯28at.com

defaults.adapter

defaults.adapter 的值如下:HxU28资讯网——每日最新资讯28at.com

// /v1.6.8/lib/defaults/index.js#L40adapter: ['xhr', 'http'],

adapters.getAdapter(['xhr', 'http']) 又是在做什么事情呢?HxU28资讯网——每日最新资讯28at.com

适配器实现

首先,adapters 位于 lib/adapters/adapters.js[4]。HxU28资讯网——每日最新资讯28at.com

所属的目录结构如下:HxU28资讯网——每日最新资讯28at.com

图片图片HxU28资讯网——每日最新资讯28at.com

可以看到针对浏览器和 Node.js 2 个环境的适配支持:http.js、xhr.js。HxU28资讯网——每日最新资讯28at.com

adapters 的实现如下。HxU28资讯网——每日最新资讯28at.com

首先,将内置的 2 个适配文件引入。HxU28资讯网——每日最新资讯28at.com

// /v1.6.8/lib/adapters/adapters.js#L2-L9import httpAdapter from './http.js';import xhrAdapter from './xhr.js';const knownAdapters = {  http: httpAdapter,  xhr: xhrAdapter}

knownAdapters 的属性名正好是和 defaults.adapter 的值 ['xhr', 'http'] 是一一对应的。HxU28资讯网——每日最新资讯28at.com

而 adapters.getAdapter(['xhr', 'http']) 的实现是这样的:HxU28资讯网——每日最新资讯28at.com

// /v1.6.8/lib/adapters/adapters.js#L27-L75export default {  getAdapter: (adapters) => {    // 1)    adapters = Array.isArray(adapters) ? adapters : [adapters];    let nameOrAdapter;    let adapter;        // 2)    for (let i = 0; i < adapters.length; i++) {      nameOrAdapter = adapters[i];      adapter = nameOrAdapter;            // 3)      if (!isResolvedHandle(nameOrAdapter)) {        adapter = knownAdapters[String(nameOrAdapter).toLowerCase()];      }      if (adapter) {        break;      }    }    // 4)    if (!adapter) {      throw new AxiosError(        `There is no suitable adapter to dispatch the request `,        'ERR_NOT_SUPPORT'      );    }    return adapter;  }}

内容比较长,我们会按照代码标准的序号分 4 个部分来讲。HxU28资讯网——每日最新资讯28at.com

1)这里是为了兼容调用 axios() 时传入 adapter 参数的情况。HxU28资讯网——每日最新资讯28at.com

// `adapter` allows custom handling of requests which makes testing easier.// Return a promise and supply a valid response (see lib/adapters/README.md).adapter: function (config) {  /* ... */},

因为接下来 adapters 是作为数组处理,所以这种场景下,我们将 adapter 封装成数组 [adapters]。HxU28资讯网——每日最新资讯28at.com

// /v1.6.8/lib/adapters/adapters.js#L28adapters = Array.isArray(adapters) ? adapters : [adapters];

2)接下来,就是遍历 adapters 找到要用的那个适配器。HxU28资讯网——每日最新资讯28at.com

到目前为止,adapters[i](也就是下面的 nameOrAdapter)既可能是字符串('xhr'、'http'),也可能是函数(function (config) {})。HxU28资讯网——每日最新资讯28at.com

// /v1.6.8/lib/adapters/adapters.js#L37let nameOrAdapter = adapters[i];adapter = nameOrAdapter;

3)那么,我们还要检查 nameOrAdapter 的类型。HxU28资讯网——每日最新资讯28at.com

// /v1.6.8/lib/adapters/adapters.js#L42-L48if (!isResolvedHandle(nameOrAdapter)) {  adapter = knownAdapters[(id = String(nameOrAdapter)).toLowerCase()];}

isResolvedHandle() 是一个工具函数,其目的是为了判断是否要从 knownAdapters 获取适配器。HxU28资讯网——每日最新资讯28at.com

// /v1.6.8/lib/adapters/adapters.js#L24const isResolvedHandle = (adapter) => typeof adapter === 'function' || adapter === null || adapter === false;

简单理解,只有 adapter 是字符串的情况('xhr' 或 'http'),isResolvedHandle(nameOrAdapter) 才返回 false,才从 knownAdapters 获得适配器。HxU28资讯网——每日最新资讯28at.com

typeof adapter === 'function' || adapter === null 这个判断条件我们容易理解,这是为了排除自定义 adapter 参数(传入函数或 null)的情况。HxU28资讯网——每日最新资讯28at.com

而 adapter === false 又是对应什么情况呢?HxU28资讯网——每日最新资讯28at.com

那是因为我们的代码只可能是在浏览器或 Node.js 环境下运行。这个时候 httpAdapter 和 xhrAdapter 具体返回是有差异的。HxU28资讯网——每日最新资讯28at.com

// /v1.6.8/lib/adapters/xhr.js#L48const isXHRAdapterSupported = typeof XMLHttpRequest !== 'undefined';export default isXHRAdapterSupported && function (config) {/* ...*/}// /v1.6.8/lib/adapters/http.js#L160const isHttpAdapterSupported = typeof process !== 'undefined' && utils.kindOf(process) === 'process';export default isHttpAdapterSupported && function httpAdapter(config) {/* ... */}

也就是说:在浏览器环境 httpAdapter 返回 false,xhrAdapter 返回函数;在 Node.js 环境 xhrAdapter 返回 false,httpAdapter 返回函数。HxU28资讯网——每日最新资讯28at.com

因此,一旦 isResolvedHandle() 逻辑执行完成后。HxU28资讯网——每日最新资讯28at.com

if (!isResolvedHandle(nameOrAdapter)) {/* ... */}

会检查 adapter 变量的值,一旦有值(非 false)就说明找到适配器了,结束遍历。HxU28资讯网——每日最新资讯28at.com

if (adapter) {  break;}

4)最终在返回适配器前做空检查HxU28资讯网——每日最新资讯28at.com

// 4)if (!adapter) {  throw new AxiosError(    `There is no suitable adapter to dispatch the request `,    'ERR_NOT_SUPPORT'  );}return adapter;

如此,就完成了跨端架构的实现。HxU28资讯网——每日最新资讯28at.com

总结

本文我们讲述了 axios 的跨端架构原理。axios 内部实际发出请求是通过 dispatchRequest() 方法处理的,再往里看则是通过适配器模式取得适应于当前环境的适配器函数。HxU28资讯网——每日最新资讯28at.com

axios 内置了 2 个适配器支持:httpAdapter 和 xhrAdapter。httpAdapter 是 Node.js 环境实现,通过 http/https 模块;xhrAdapter 这是浏览器环境实现,通过 XMLHttpRequest API 实现。Node.js 环境 xhrAdapter 返回 false,浏览器环境 httpAdapter 返回 false——这样总是能返回正确的适配器。HxU28资讯网——每日最新资讯28at.com

参考资料

[1]axios 是如何实现取消请求的?: https://juejin.cn/post/7359444013894811689HxU28资讯网——每日最新资讯28at.com

[2]你知道吗?axios 请求是 JSON 响应优先的: https://juejin.cn/post/7359580605320036415HxU28资讯网——每日最新资讯28at.com

[3]Axios: https://github.com/axios/axios/blob/v1.6.8/lib/core/Axios.jsHxU28资讯网——每日最新资讯28at.com

[4]lib/adapters/adapters.js: https://github.com/axios/axios/blob/v1.6.8/lib/adapters/adapters.jsHxU28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-87048-0.htmlAxios 跨端架构是如何实现的?

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 盘点Lombok的几个操作,你记住了吗?

下一篇: Python 网络爬虫利器:执行 JavaScript 实现数据抓取

标签:
  • 热门焦点
  • 天猫精灵Sound Pro体验:智能音箱没有音质?来听听我的

    这几年除了手机作为智能生活终端最主要的核心之外,第二个可以成为中心点的产品是什么?——是智能音箱。 手机在执行命令的时候有两种操作方式,手和智能语音助手,而智能音箱只
  • 2023年Q2用户偏好榜:12+256G版本成新主流

    3月份的性能榜、性价比榜和好评榜之后,就要轮到2023年的第二季度偏好榜了,上半年的新机潮已经过去,最明显的肯定就是大内存和存储的机型了,另外部分中端机也取消了屏幕塑料支架
  • 摸鱼心法第一章——和配置文件说拜拜

    为了能摸鱼我们团队做了容器化,但是带来的问题是服务配置文件很麻烦,然后大家在群里进行了“亲切友好”的沟通图片图片图片图片对比就对比,简单对比下独立配置中心和k8s作为配
  • 不容错过的MSBuild技巧,必备用法详解和实践指南

    一、MSBuild简介MSBuild是一种基于XML的构建引擎,用于在.NET Framework和.NET Core应用程序中自动化构建过程。它是Visual Studio的构建引擎,可在命令行或其他构建工具中使用
  • Java NIO内存映射文件:提高文件读写效率的优秀实践!

    Java的NIO库提供了内存映射文件的支持,它可以将文件映射到内存中,从而可以更快地读取和写入文件数据。本文将对Java内存映射文件进行详细的介绍和演示。内存映射文件概述内存
  • JavaScript学习 -AES加密算法

    引言在当今数字化时代,前端应用程序扮演着重要角色,用户的敏感数据经常在前端进行加密和解密操作。然而,这样的操作在网络传输和存储中可能会受到恶意攻击的威胁。为了确保数据
  • 虚拟键盘 API 的妙用

    你是否在遇到过这样的问题:移动设备上有一个固定元素,当激活虚拟键盘时,该元素被隐藏在了键盘下方?多年来,这一直是 Web 上的默认行为,在本文中,我们将探讨这个问题、为什么会发生
  • 得物宠物生意「狂飙」,发力“它经济”

    作者|花花小萌主近日,得物宣布正式上线宠物鉴别,通过得物App内的&ldquo;在线鉴别&rdquo;,可找到鉴别宠物的选项。通过上传自家宠物的部位细节,就能收获拥有专业资质认证的得物鉴
  • 最薄的14英寸游戏笔记本电脑 Alienware X14已可以购买

    2022年1月份在国际消费电子展(CES2022)上首次亮相的Alienware新品——Alienware X14现在已经可以购买了,这款笔记本电脑被誉为世界上最薄的 14 英寸游戏笔
Top