前端常见请求方式AJAX、Fetch、SSE、Websocket、Beacon

1. DOM标签

在HTML中,有很多标签可以用来发起HTTP请求。以下是最常见的一些:

  1. <a>:此标签用于创建一个链接,当用户点击链接时将发起请求到指定的URL。

    html 复制代码
    <a href="http://example.com">Visit Example</a>
  2. <img>:此标签用于加载图片,浏览器会发送请求去获取对应的src的图片资源。

    html 复制代码
    <img src="image.jpg" alt="My test image">
  3. <link>:此标签通常位于HTML文件的<head>部分,用于引入CSS文件。

    html 复制代码
    <link rel="stylesheet" type="text/css" href="styles.css">
  4. <script>:此标签用于引入JavaScript文件。

    html 复制代码
    <script src="script.js"></script>
  5. <iframe>:此标签用于嵌入另一个HTML页面。

    html 复制代码
    <iframe src="http://example.com"></iframe>
  6. <video> and <audio>:这两个标签用于嵌入视频和音频内容。

    html 复制代码
    <video src="myVideo.mp4" controls></video>
    <audio src="myAudio.mp3" controls></audio>
  7. <object><embed><source>等也能发起请求。

请注意,以上的所有请求都是浏览器根据HTML内容自动发起的,不需要做额外的配置。

如果使用js进行获取呢?

JavaScript 并不能直接获取到HTML标签请求的结果,但可以通过监听事件和使用一些DOM 属性来间接得到一些信息。以下是一些常见的方法:

  1. 以img为例,为图像添加 loaderror 事件:
ini 复制代码
javascript复制代码
var img = new Image();
img.src = 'http://example.com/image.jpg';
img.onload = function() {
    console.log('Image has loaded');
};
img.onerror = function() {
    console.log('An error occurred while loading image');
};

我们并没有直接获取到图片的内容,但是我们知道图片何时加载成功,或者是否出错,可以获取返回的内容。

2. AJAX

2.1 概念

AJAXAsynchronous JavaScript and XML的缩写,即异步的JavaScript和XML。它是一种在不重新加载整个网页的情况下,与服务器交换数据并更新部分网页的技术。

AJAX的核心是XMLHttpRequest对象,它提供了一个API,使得浏览器可以通过JavaScript向服务器发送请求并接收响应。 XMLHttpRequest是一个浏览器对象,用于在不重新加载页面的情况下向服务器发送HTTP请求并获取响应。它是AJAX技术的核心组成部分之一,用于实现异步数据交互。

2.2 案例

  1. 请求过程
markdown 复制代码
1. 创建ajax对象 
2. 调用ajax对象的open 函数  准备发送请求 
3. 调用ajax对象的send 函数  发送请求  但是请求还没有到达服务器 
4. 调用ajax对象的监听函数 onreadystatechange   监听ajax的创建过程 
      readystate  ajax 的状态码 
        0  准备创建ajax
              new XMLHttpRequest();
        1  发送了请求  服务器尚未接到数据 [客户端和服务器   建立了链接]
              open()
              send()
        以下这些状态码 都是服务器对客户端数据进行操作的状态     
        2  发送了请求  服务器接受到了请求 

        3  服务器接收到了请求 并且在处理请求 

        4  服务器处理请求成功  响应给客户端 

      status  相应状态码  表示 readystate === 4 
         服务器已经向客户端响应了数据 
           状态码 会判断 服务器相应数据的状态 
             200 ok   响应成功 
             404      响应的页面没有找到 
             500      服务器产生异常 失败
  1. 案例
js 复制代码
<button id="btn">获取数据</button>
<h1 id="h1">
	希望获取新加载的数据
</h1>
<div id="content">
	原有的数据........
</div>
<script>

	// 注册事件
	const btnNode = document.querySelector("#btn");
	const contentNode = document.getElementById('content')

	// 注册onclick事件 
	btnNode.onclick = function () {
		// 1. 创建ajax 对象 
		// 高版本浏览器创建的对象 
		let xhr;
		if (window.XMLHttpRequest) {
			xhr = new XMLHttpRequest();
		} else {
			// IE5  IE6 低版本浏览器 
			xhr = new ActiveXObject("Microsoft.XMLHTTP")
		}

		// 2. 准备发送请求 
		/*
		参数
			1.  请求方式  get/post/put/delete
			2.  请求位置  url
			3.  是否是异步请求 
						 true  表示异步
						 false 表示同步
		*/
		xhr.open("POST", "http://localhost:3000/api/xhr", true)
		// 设置请求头
		xhr.setRequestHeader("token", "888888888")

		// 3. 发送请求 
		xhr.send()

		// 4.  监听ajax的整个过程
		// onreadystatechange 监听ajax 发送的事件 
		xhr.onload = function () {
			console.log('打印***onload')
			const data = xhr.responseText;
			//获取h1 节点 
			const h1Node = document.getElementById("h1")
			h1Node.innerText = data;
			console.log(data);
		}
	}
</script>

其中第四步可以使用xhr.onload进行替换

js 复制代码
xhr.onload = function(){
    const data = xhr.responseText;
    //获取h1 节点 
    const h1Node = document.getElementById("h1")
    h1Node.innerText = data;
    console.log(data);
}

2.3 xhr.onloadxhr.onreadystatechange两者的区别

xhr.onloadxhr.onreadystatechange执行相同的操作:在一个异步请求的各种生命周期阶段接收通知。但是,它们的使用方式有一些差异。

xhr.onreadystatechange:

onreadystatechange事件会在readyState属性值改变时触发。这意味着你需要检查readyState值并确定请求是否完成。如果readyState等于4,那么请求已经完成并且响应已经就绪。

ini 复制代码
javascript复制代码
xhr.onreadystatechange = function() {
    if (xhr.readyState === 4 && xhr.status === 200) {
        console.log(xhr.responseText);
    }
};

xhr.onload:

相比之下,xhr.onload事件只在请求成功完成时触发。不需要检查readyState或状态代码,因为如果触发了onload事件,那么就可以确保请求已经成功完成。

ini 复制代码
javascript复制代码
xhr.onload = function() {
    console.log(xhr.responseText);
};

xhr.onload提供了一个更简洁、更直观的方式来处理成功的HTTP请求。然而,如果你需要更细粒度的控制(例如,你想在请求的不同阶段执行不同的操作),那么xhr.onreadystatechange可能会是一个更好的选择。

2.4 基于ajax封装的库有axios

3. fetch

3.1 概念

Fetch 是 XMLHttpRequest 的升级版,用于在 JavaScript 脚本里面发出 HTTP 请求。

3.2 案例

js 复制代码
<button id="btn">获取数据</button>
<h1 id="h1">
	希望获取新加载的数据
</h1>
<div id="content">
	原有的数据........
</div>
<script>

	// 注册事件
	const btnNode = document.querySelector("#btn");

	// 注册onclick事件 
	btnNode.onclick = function () {
		fetch('http://localhost:3000/api/fetch', {
			headers: {
				token: '66666666666'
			}
		}).then(res => {
			return res.text()
		}).then(data => {
			const h1Node = document.getElementById("h1")
			h1Node.innerText = data;
		})

	}

</script>

3.3 基于fetch封装的库umi-request


总结ajax和fetch区别

功能点 XHR Fetch
基本请求、获取响应能力
监控请求进度 x
监控响应进度
Service-Worker中是否可用 x
控制cookie的携带 x
控制重定向 x
请求取消
自定义referrer x
x
API风格 Event Promise
活跃度 x

4. websocket

4.1 概念

WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就可以直接创建持久性的连接,并进行双向数据传输。

现在许多网站的实时功能(例如聊天,实时游戏等)都是使用 WebSocket 实现的。它解决了 HTTP 协议只能由客户端向服务端发起请求的问题,使得服务端也能主动向客户端发送数据。

4.2 案例

js 复制代码
<button id="btn">获取数据</button>
<h1 id="h1">
	希望获取新加载的数据
</h1>
<div id="content">
	原有的数据........
</div>
<script>

	// 注册事件
	const btnNode = document.querySelector("#btn");
	const h1Node = document.getElementById("h1")

	// 注册onclick事件 
	btnNode.onclick = function () {

		const socket = new WebSocket('ws://localhost:3000');

		socket.onopen = function () {
			console.log('连接已建立');
		};

		socket.onmessage = function (event) {
			const data = event.data;
			console.log('接收到服务器发送的消息:', data);
			h1Node.innerText = data;
		};

		socket.onclose = function () {
			console.log('连接已关闭');
		};
		// 心跳
		setInterval(() => {
			socket.send('ping');
		}, 3000);

}
</script>

4.3 基于websocket 封装的库socket.io

5. Beacon

5.1 概念

Beacon API 用于发送异步和非阻塞请求到服务器。这类请求不需要响应。与 XMLHttpRequestFetch API 请求不同,浏览器会保证在页面卸载前,将信标请求初始化并运行完成。

Beacon API 的优点是,它可以在浏览器关闭或离开当前页面时异步发送数据到服务器,而不会阻塞页面的操作或等待服务器的响应。这对于进行统计分析、性能监控和日志记录等后台数据收集的场景非常有用。

5.2 案例

js 复制代码
<button id="btn">获取数据</button>
<h1 id="h1">
	希望获取新加载的数据
</h1>
<div id="content">
	原有的数据........
</div>
<script>

	// 注册事件
	const btnNode = document.querySelector("#btn");
	const h1Node = document.getElementById("h1")

	// 注册onclick事件 
	btnNode.onclick = function () {
		const data = {
			event: '按钮点击',
			timestamp: new Date().toISOString(),
			userAgent: navigator.userAgent
		};
		// 调用发送数据的函数, 返回true
	  const res =  navigator.sendBeacon('http://localhost:3000/api/beacon', JSON.stringify(data))
		h1Node.innerText = res
	}

</script>

6. SSE(Eventsource)

6.1 概念

Server-Sent Events(SSE)是一种基于HTTP的服务器向客户端发送更新的技术。与WebSockets类似,SSE也允许服务器向客户端推送实时更新。然而,不同于WebSockets提供的双向通信,SSE是单向的:只允许服务器向客户端发送数据。

SSE 是基于HTTP的,因此比WebSocket更容易使用,并且与现有的HTTP基础设施兼容性更好。使用SSE,你可以使用传统的HTTP请求到服务器上开启一个持久连接,服务器可以通过这个连接连续地发送消息。

6.2 案例

js 复制代码
<button id="btn">获取数据</button>
<h1 id="h1">
	希望获取新加载的数据
</h1>
<div id="content">
	原有的数据........
</div>
<script>

	// 注册事件
	const btnNode = document.querySelector("#btn");
	const h1Node = document.getElementById("h1")

	// 注册onclick事件 
	btnNode.onclick = function () {
		// 创建一个EventSource对象,连接到服务器端的SSE端点
		const eventSource = new EventSource('http://localhost:3000/api/sse');

		// 监听服务器端发送的消息
		eventSource.onmessage = (event) => {
			console.log(event.data);
			const data = event.data
			h1Node.innerText = data;
			// 在这里处理服务器端发送的消息
		};

		// 监听连接关闭事件
		eventSource.onclose = () => {
			console.log('SSE connection closed');
		};

		// 监听错误事件
		eventSource.onerror = (error) => {
			console.error('SSE error:', error);
		};
	}
</script>

7. 以上案例服务端代码

使用koa进行编写:

js 复制代码
const Koa = require('koa')
const Router = require('koa-router')
const websockify = require('koa-websocket')
const cors = require('koa2-cors')
const { koaBody } = require('koa-body');

const app = new Koa();

app.use(koaBody());


// 使用koa2-cors中间件解决跨域
app.use(cors())

const router = new Router()

//  使用 koa-websocket 将应用程序升级为 WebSocket 应用程序
const appWebSocket = websockify(app)

// webSocket
appWebSocket.ws.use((ctx, next) => {
	// 存储新连接的客户端
	clients.add(ctx.websocket)
	// 处理连接关闭事件
	ctx.websocket.on('close', () => {
		clients.delete(ctx.websocket)
	})
	ctx.websocket.on('message', (data) => {
		console.log('打印***data', data)
		ctx.websocket.send('pong' + Math.random())
	})
	ctx.websocket.on('error', (err) => {
		console.log('打印***err', err)
		clients.delete(ctx.websocket)
	})

	return next(ctx)
})

// xhr
router.post('/api/xhr', (ctx) => {
	ctx.body = 'I am xhr!'
})
// fetch
router.get('/api/fetch', (ctx) => {
	ctx.body = 'I am fetch!'
})
// beacon
router.post('/api/beacon', (ctx) => {
	const data = ctx.request.body
	console.log('打印***data', data)
	ctx.body = 'I am beacon!'
})
// sse
router.get('/api/sse', (ctx) => {

	ctx.respond = false
	ctx.res.writeHead(200, {
		"Content-Type": "text/event-stream",
		"Cache-Control": "no-cache",
		Connection: "keep-alive",
	});

	// 发送初始事件数据
	ctx.res.write(`data: I am sse!\n\n`);

	// 定期发送事件数据
	setInterval(() => {
		ctx.res.write(`data: This is a SSE message at ${new Date().toISOString()}\n\n`);
	}, 1000);
})

// 将路由注册到应用程序
appWebSocket.use(router.routes()).use(router.allowedMethods())

// 启动服务器
appWebSocket.listen(3000, () => {
	console.log('Server started on port 3000')
})

8. 总结

主要介绍了几种前端常见的请求方式:

  1. xhr
  2. fetch
  3. websocket
  4. eventsource
  5. sendBeacon
  6. 常见标签请求

总结一下常见原生常见请求的方式,希望对大家的认识有一点帮助。文中如有错误,请指正O^O!


笔记

汇总

一文搞懂前端请求XHR,AJAX,Fetch和Axios

相关推荐
mldong3 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排3 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60614 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角5 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!5 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰5 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi7 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen7 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马8 小时前
AI源码分析:拆解模型底层实现逻辑
前端
IT_陈寒8 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端