Skip to content

每日两题

这个系列将会每日更新两题面试题,虽然我不是每题都有实力解答,但是我还是能尽我所能动用所有资源来写出最好的答案。

今天的题目只有一题,不要问为什么 doge。

Ajax, Axios, Fetch 的区别

我们先来分别了解一下每个东西。

Ajax

Ajax 是 Asynchronous JavaScropt And XML 的缩写,被译为异步的 JS 和 XML。它本身并不是一项新技术,而是一个在 2005 年被Jesse James Garrett提出的新术语。

通过 ajax 可以在浏览器向服务器发送异步请求,最大的优势在于无刷新获取数据。它是一种将现有的标准组合在一起使用的新方式。

尽管 Ajax 中的 “X” 代表 XML ,但由于 JSON 的许多优势,目前 JSON 的使用比 XML 更加普遍。 JSON 和 XML 都被用于在 Ajax 模型中封装数据。

异步交互的优劣

异步交互相比同步交互的优势主要具有以下几点:

  • 用户操作无需像同步交互必须等待结果
  • 异步交互只需与服务端交换必要的数据内容,而不是将所有数据全部更新
  • 异步交互对带宽造成的压力相比同步交互更小
  • 通过 ajax 实现异步交互不需要任何第三方插件,只要浏览器支持 JavaScript 语言即可

但它也存在一些问题:

  • 异步交互破坏了浏览器原有的前进和后退机制
  • 如果后面逻辑的执行依靠前面逻辑执行的结果的话,异步交互可能会造成问题
  • ajax 实现异步交互对搜索引擎(SEO)支持较弱
  • ajax 实现异步交互会引起一些 Web 安全问题,例如 SQL 注入攻击、跨站点脚本攻击等问题

涉及的技术和核心

Ajax 只是为实现异步交互的手段,不是一种技术,而是多种技术的整合。其中包含以下几种技术:

  • HTML 页面
  • CSS
  • JavaScript
  • DOM
  • XML
  • XMLHttpRequest 对象

实现 ajax 异步交互的核心就是XMLHttpRequest对象,该对象为客户端提供了在客户端和服务器之间传输数据的功能。

XMLHttpRequest对象提供了一个通过 URL 来获取数据的简单方式,并且不会使整个页面刷新。这使得网页只更新一部分页面而不会打扰到用户。

XMLHttpRequest对象对象最初由微软设计,随后被 Mozilla、Apple 和 Google 采纳,如今已被 W3C 组织标准化。通过该对象,可以很容易地得到一个 URL 上的资源数据。尽管名字里 XML, 但 XMLHttpRequest 对象可以得到所有类型的数据资源,并不局限于 XML 格式的数据。

实现异步交互

作为客户端的 HTML 页面需要完成以下步骤:

  1. 创建 Ajax 的核心对象 XMLHttpRequest 对象
  2. 通过该对象的open()方法与服务器端建立连接
  3. 构建请求所需的数据内容,并通过该对象的send()方法发送给服务器端
  4. 通过该对象提供的onreadystatechange事件监听服务器端的通信状态
  5. 接受并处理服务器端响应的数据结果
  6. 将处理结果更新到 HTML 页面中

以下只是为了实现简单的异步交互,并只介绍对应的方法,若需要了解整个 xhr 对象上的方法,请前往MDN查阅

js
const request = new XMLHttpRequest()

/**
 * @param method 当前请求的方式
 * @param url 当前请求的服务器端地址
 * @param async 可选的布尔参数,表示是否异步执行操作,默认true
 * @param user 可选的用户名用于认证用途,默认null
 * @param password 可选的密码用于认证用途,默认null
 */
request.open(method, url, [async][, user][, password])

/**
 * @param body 在xhr请求中要发送的数据体,如果不传递数据则为null
 */
request.send([body])

/**
 * onreadystatechange事件用于监听服务器端的通信状态,它依靠
 * XMLHttpRequest.readyState属性,该属性返回一个XMLHttpRequest
 * 代理当前所处的状态,只要当前属性值被改变就会触
 * onreadystatechange事件。该属性有五种状态。
 *
 * 值   状态              描述
 * 0    UNSENT            代理被创建,但尚未调用open()
 * 1    OPENED            open()已被调用
 * 2    HEADERS_RECEIVED  send()已被调用,且头部和状态已经可获得
 * 3    LOADING           正在响应
 * 4    DONE              响应已完毕
 *
 * XMLHttpRequest.responseText属性用于接收服务器端的响应结果
 */
request.onreadystatechange = function () {}
html
<body>
  <button id="btn">click</button>
  <script>
    const btn = document.getElementById('btn')
    btn.addEventListener('click', function () {
      const xhr = new XMLHttpRequest()

      xhr.open('GET', 'https://...')

      xhr.send(null)

      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          console.lg(xhr.responseText)
        }
      }
    })
  </script>
</body>

交互的问题

onreadystatechange 事件的绑定位置

绑定位置不同,readyState属性的结果不一样,上面的代码readyState属性执行的结果为

txt
2
3
4

如果我们修改一下位置呢?

html
<script>
  const btn = document.getElementById('btn')
  btn.addEventListener('click', function () {
    const xhr = new XMLHttpRequest()

    xhr.onreadystatechange = function () {
      console.lg(xhr.readyState)
    }

    xhr.open('GET', 'https://...')

    xhr.send(null)
  })
</script>

结果会是:

txt
1
2
3
4

但是我们不可能的达到状态 0,是因为我们在绑定这个之前必须完成对象的初始化。

send()的问题

如果为GET方法的话,send()中只能传递 null,如果需要添加请求数据的话需要添加在地址中。

js
open('GET', 'http://...?name=value&name2=value2')

post 请求

调用send()前,open()后,需要通过 XHR 对象的setRequestHeader()方法设置请求头信息。

js
xhr.setRequestHeader(header, value)

// eg
xhr.setRequestHeader('Content-Type', 'application/json')

然后再在send()中发送请求数据

Axios

Axios通过 promise 实现对 ajax 技术的一种封装的 HTTP 库,可以用在浏览器和 node.js 中,它的特性:

  • 从浏览器中创建XMLHttpRequest
  • 从 node.js 创建 http 请求
  • 支持Promise API
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换 JSON 数据
  • 客户端支持防御 XSRF

其实 axios 上并没有什么原理可将的,但是它的实现(源码)可以了解了解和一些常用方法以及特点可以熟悉一下。

之后我会查阅资料并找到并记录能详细了解 axios 的各个方面。

Fetch

Fetch是是前端发展的一种新技术产物。Fetch API 提供了一个 JavaScript 接口,用于访问和操纵 HTTP 管道的部分,例如请求和响应。它还提供了一个全局 fetch()方法,该方法提供了一种简单,合理的方式来跨网络异步获取资源。

这种功能以前是使用 XMLHttpRequest 实现的。Fetch 提供了一个更好的替代方法,可以很容易地被其他技术使用,例如 Service Workers。Fetch 还提供了单个逻辑位置来定义其他 HTTP 相关概念,例如 CORS 和 HTTP 的扩展。

使用 fetch 的时候需要注意:

  • 当接收到一个代表错误的 HTTP 状态码时,从fetch()返回的 Promise 不会被标记为 reject,即使 HTTP 响应的状态码是 404 或 500。相反,它会将 Promise 状态标记为 resolve(但是会将 resolve 的返回值的 ok 属性设置为 false),仅当网络故障时或请求被阻止时才会标记为 reject
  • 默认情况下,fetch 不会从服务器端发送或接收任何 cookies,如果站点依赖于用户 session,则会导致未经认证的请求(要发送 cookies 必须设置 credentials 选项)

Fetch 代表着更先进的技术方向,但是目前兼容性不是很好,暂时不考虑展开详细讲。

区别

通过上面的一些简单了解,在不同的技术上的区别在于 Fetch 和 XMLHttpRequest。他们的差异在于:

  • fetch 使用 Promise,不使用回调函数,因此大大简化了写法,写起来更简洁
  • fetch 采用模块化设计,API 分散在多个对象上(Response 对象、Request 对象、Headers 对象),更合理一些;相比之下,XMLHttpRequest 的 API 设计并不是很好,输入输出和状态都在同一个接口管理,容易写出非常混乱的代码
  • fetch 通过数据流(Stream 对象)处理数据,可以分块读取,有利于提高网站性能表现,减少内存占用,对于请求大文件或者网速慢的场景相当有用。XMLHttpRequest 对象不支持数据流,所有的数据必须放在缓存中,不支持分块读取,必须等待全部拿到后,再一次性吐出来。
  • fetch 不支持abort,,不支持超时控制,基于 setTimeout 及 Promise.reject 的实现的超时控制并不能阻止请求过程继续再后台运行
  • fetch 没有办法原生监测请求进度,xhr 可以
  • fetch 默认不会带 cookie,需要添加配置项 crendentials
  • fetch 只对网络请求和请求被阻止报错

那在相同的实现方法层面上,区别就在于 ajax 和 axios 之间的区别并不大,只不过 axios 是 ajax 的封装,axios 有的 ajax 都有,ajax 有的 axios 不一定有。

他们三者的关系可以用下面的图概括:

Ajax和Axios和Fetch的关系(图片来自https://blog.csdn.net/weixin_52148548/article/details/124667729)Ajax和Axios和Fetch的关系(图片来自https://blog.csdn.net/weixin_52148548/article/details/124667729)

参考

一篇博客搞懂 Ajax 是什么

深入理解 Axios 核心原理

Fetch API 教程

转载请标注本站原文地址