10分钟了解ajax
2024-07-06 05:05:44

面试官:ajax是什么?我:啥?这不是JQuery封装的工具方法吗?

正文

不得不说,模拟面试那时候,什么刁钻的问题几乎都接触过,用这种远古问题拷打我,真是。。。绝了。

我还没答上来,真是,绝妙。

AJAX定义

AJAX 代表异步的 JavaScript 和 XML(Asynchronous JavaScript And XML)。

简单点说,就是使用 XMLHttpRequest 对象与服务器通信。它可以使用 JSON、XML (Extensible Markup Language)、HTML 和文本文件等格式发送和接收数据

AJAX 最吸引人的就是它的异步特性,也就是说它可以在不重新刷新页面的情况下与服务器通信、交换数据或更新页面

整个流程很简单,如下

  1. 创建一个XMLHttpRequest对象,发送异步请求HttpRequest
  2. 服务器通过网络,接收HttpRequest请求,返回请求数据
  3. 浏览器通过网络,接收服务器返回的数据,用JS操作DOM更新页面

为避免混淆,这里重新梳理一下 Ajax 概念:

  1. AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)
  2. AJAX 不是编程语言,而是一种基于现有标准的新方法
  3. AJAX 最大的优点是在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页内容
  4. AJAX 不需要任何浏览器插件,但需要用户允许 JavaScript 在浏览器上执行。
  5. XMLHttpRequest 只是实现 Ajax 的一种方式

总的来说,AJAX是浏览器与服务器进行数据通信的技术

AJAX实现

URL

URL (Uniform Resource Locator) 统一资源定位符(统一资源定位器、定位地址、URL地址)俗称地址,是因特网上标准的资源的地址,如同在网络上的门牌,用于访问网络上的资源

URL组成:URL 由协议域名资源路径组成

  • 协议:URL 使用 http 协议(超文本传输协议),规定浏览器与服务器之间传输数据的格式
  • 域名:标记服务器在互联网中的方位
  • 资源路径:标记资源在浏览器下的具体位置

比如,我们这里架假设要去访问百度网站上的一份文件

1
http://www.baidu.com/test/helloworld.txt

这里我们将上述url拆分一下,结果如下

访问协议 服务器名称:域名 目录名 文件名
http: www.baidu.com test helloworld.txt

域名这里如果细说,还要提到IP和端口,这里暂时先跳过,下期再说。

XMLHttpRequest

XHR概念

XMLHttpRequest(XHR)对象用于与服务器交互

通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL 来获取数据。

这允许网页在不影响用户操作的情况下,更新页面的局部内容。

XMLHttpRequestAJAX 编程中被大量使用,所有现代浏览器均支持 XMLHttpRequest 对象

XMLHttpRequest 可以用于获取任何类型的数据,而不仅仅是 XML,它甚至支持 HTTP 以外的协议(包括 file:// 和 FTP),尽管可能受到更多出于安全等原因的限制

XHR使用

实现 Ajax异步交互需要完成以下步骤:

  • 创建 XMLHttpRequest 对象
  • 通过 XMLHttpRequest 对象的 open() 方法与服务端建立连接
  • 构建请求所需的数据内容,并通过 XMLHttpRequest 对象的 send() 方法发送给服务器端
  • 通过 XMLHttpRequest 对象提供的 readystatechange、loadend 事件监听服务器端的通信状态
  • 接受并处理服务端向客户端响应的数据结果
  • 将处理结果更新到 HTML页面中
向服务器发送请求

如需将请求发送到服务器,我们使用 XMLHttpRequest 对象的 open()send() 方法

open()

  • 通过 XMLHttpRequest 对象的 open() 方法与服务器建立连接

  • 语法

    1
    xhr.open(method, url, [async][, user][, password])
  • 参数说明

    参数 说明
    method 表示当前的请求方式,常见的有 GETPOST
    url 服务端地址
    async 布尔值,表示是否异步执行操作,默认为 true(异步)
    user 可选的用户名用于认证用途;默认为 null
    password 可选的密码用于认证用途,默认为 null

send()

  • 通过 XMLHttpRequest 对象的 send() 方法,将客户端页面的数据发送给服务端

  • 语法

    1
    2
    // body为 XHR 请求中要发送的数据体(string),如果不传递数据则为 null
    xhr.send([body])
onreadystatechange

当请求被发送到服务器时,我们需要执行一些基于响应的任务。

每当 readyState 改变时(存有 XMLHttpRequest 状态信息)就会触发 readystatechange 事件

以下是 XMLHttpRequest 对象的三个重要的属性:

属性 描述
onreadystatechange 存储函数(或函数名),每当 readyState 属性改变时,就会调用该函数
readyState 存有 XMLHttpRequest 的状态。从 0 到 4 发生变化 0:请求未初始化 1:服务器连接已建立 2:请求已接收 3:请求处理中 4:请求已完成,且响应已就绪
status 200:”OK”,404:未找到页面

readystatechange 事件被触发四次,分别是:0-1、1-2、2-3、3-4,对应着 readyState 的每个变化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 旧写法
xhr.onreadystatechange = function(){
  if (xhr.readyState == 4 && xhr.status == 200 ) {
// 在这里处理服务器的响应数据
   console.log(xhr.responseText)
  } else {
// 在这里处理服务器的响应数据
   console.log(xhr.statusText)
  }
}

// 新写法
xhr.addEventListener('readystatechange', () => {
if (xhr.readyState === 4 && xhr.status === 200) {
// 在这里处理服务器的响应数据
console.log(xhr.response)
}
})
服务器响应

获取 XMLHttpRequest 响应体

1
2
3
4
5
6
7
8
9
function readBody(xhr) {
if (!xhr.responseType || xhr.responseType === "text") {
return xhr.responseText
} else if (xhr.responseType === "document") {
return xhr.responseXML
} else {
return xhr.response
}
}
XHR使用示例
  • GET 请求
1
2
3
4
5
6
7
8
const xhr = new XMLHttpRequest()
xhr.open('GET','http://xxxx.com/xxx/xxx?参数名1=值1&参数名2=值2')

xhr.addEventListener('loadend',()=>{
console.log(xhr.response)
})

xhr.send()
  • POST 请求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// POST请求,要设置请求头,请求体携带JSON字符串
const xhr = new XMLHttpRequest()
xhr.open('POST', 'http://xxx/api/register')

xhr.addEventListener('readystatechange', () => {
if (xhr.readyState === 4 && xhr.status === 200) {
// 在这里处理服务器的响应数据
console.log(xhr.response)
}
})

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

const obj = {
username: 'xxx',
password: 'xxx'
}

xhr.send(JSON.stringify(obj))

相关概念拓展

请求方式

与 POST 相比,GET 更简单也更快,并且在大部分情况下都能用。

但在以下情况中,请使用 POST 请求:

  • 不愿使用缓存文件(更新服务器上的文件或数据库)
  • 向服务器发送大量数据(POST 没有数据量限制)
  • 发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠

常见 GET 请求

1
2
xhr.open("GET", "/try/ajax/demo.php?fname=Henry&lname=Ford", true)
xhr.send()

常见 POST 请求

1
2
3
xhr.open("POST","/try/ajax/demo.php",true)
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded")
xhr.send("fname=Henry&lname=Ford")

POST 方式发送数据,需要设置请求头,并且使用send方法传递参数

Content-Type

Content-Type是 HTTP 头部字段之一,用于指示请求或响应消息的媒体类型

以下是常见的Content-Type格式:

  • application/json:用于传输 JSON 格式的数据
  • application/xml:用于传输 XML 格式的数据
  • text/plain:纯文本格式,通常用于普通文本文件
  • text/html:用于传输 HTML 格式的数据
  • image/jpeg, image/png, image/gif:用于传输图像数据
  • multipart/form-data:通常用于上传文件,表单数据会被编码成一系列的部分
  • application/x-www-form-urlencoded:通常用于发送表单数据,数据会被编码为键值对的形式(表单默认的提交数据的格式)

在 HTTP 协议中,如果未明确指定 Content-Type 头部字段,默认值取决于请求或响应的具体情况:

  • 对于请求(Request)
    • 对于常见的表单提交,即 application/x-www-form-urlencoded
    • 对于通过表单上传文件的情况,即 multipart/form-data
  • 对于响应(Response)
    • 如果服务器响应包含实际的数据,而不仅仅是一条状态码和头部字段,则常见的默认值为 application/octet-stream,表示二进制流,没有指定具体的数据类型

HTTP 协议规范允许在请求和响应中都不设置 Content-Type 头部字段。

在这种情况下,接收方可能需要根据上下文来猜测数据的类型,这可能引入一些不确定性。

推荐在请求和响应中显式地设置 Content-Type 头部字段

FormData

Ajax 操作往往用来传递表单数据。为了方便表单处理,HTML5 新增了一个 FormData 对象,可以模拟表单,特别适用于发送包含文件上传等复杂数据的请求

使用 FormData 可以执行以下步骤:

  • 创建一个 FormData 对象
1
const formData = new FormData()
  • 向 FormData 对象中添加字段
1
2
formData.append('username', 'John')
formData.append('email', 'john@example.com')
  • 添加文件类型的字段
1
2
3
// 从文件输入框中获取选中的文件, 可以根据实际情况选择获取文件的方式
const fileInput = document.getElementById('fileInput')
formData.append('file', fileInput.files[0])
  • 将 FormData 对象作为请求的 body 或附加到 XMLHttpRequest 或 fetch 等发送请求的方法中:
1
2
3
const xhr = new XMLHttpRequest()
xhr.open('POST', '/api/endpoint')
xhr.send(formData)

以上就将 FormData 数据作为请求的一部分发送给服务器端了

注意事项:

  • 当使用 FormData 时,浏览器会自动设置适当的 Content-Type 头部,无需手动设置
  • FormData 也支持删除字段和追加相同字段名的多个值等操作,请根据需求使用相应的方法

FormData 对象其他方法参考官网:MDN-FormData

结语

说实话,早年就以为这东西是jquery封装的,结果上次模拟面试被狠狠拷打了一波。

虽然这种远古问题不应该算是关注范围以内的东西了,但是有备无患,这里记录一下。

2024年了,我居然又翻到ajax了,真是。。绝了。

这两天把ajax,axios,fetch相关的请求方式全整理一遍,不然面试还真有点发憷。

参考

一文熟悉Ajax

MDN-CN