文章目录
1. AJAX
1.1 基本概念
- AJAX是一门异步的用于发送网络请求的计算
- 允许浏览器与服务器通信,而无序刷新当前页面的技术叫做 AJAX
- AJAX是 Asynchronous JavaScript and XML 的缩写
1.2 GET请求步骤
// 1.创建请求对象
const XHR = new XMLHttpRequest()
// 2.设置请求对象
XHR.open("GET", "http://xxx:9527/xxx")
// 3.设置请求头,GET请求不需要设置请求头
// XHR.setRequestHeader()
// 4.发送请求
XHR.send()
// 5.监听请求的状态
XHR.onreadystatechange = function () {
// XHR.readyState ==> 请求过程
// (1).请求未初始化,在open之前 --> 0
// (2).服务器连接已经建立,在open之后 --> 1
// (3).请求已经接收 --> 2
// (4).请求处理中 --> 3
// (5).请求已完成,且响应已经就绪 --> 4
// 6.处理请求结果
if (XHR.readyState === 4) {
// XHR.status 请求状态码
if (XHR.status >= 200 && XHR.status < 300) {
// 返回的是JSON格式
console.log(JSON.parse(XHR.response));
} else {
console.log("请求失败");
}
}
}
// 7.超时处理
// 终止请求
XHR.timeout = 10000
// 取消请求
XHR.abort();
1.3 POST请求步骤
// 1.创建请求对象
const XHR = new XMLHttpRequest()
// 2.设置请求对象
XHR.open("POST", "http://xxx:9527/xxx")
// 3.设置请求头
// POST:提交数据需要告知服务端数据格式(设置请求头)
// application/x-www-form-urlencoded --> name=xiaohong&age=18
// application/json --> JSON.stringify({"name": "xiaohong","age": 18})
XHR.setRequestHeader("Content-Type", "application/json")
let params = { "name": "鲁班", "words": "鲁班大师智商250" }
// 4.发送请求
XHR.send(JSON.stringify(params))
// 5.监听请求的状态
XHR.onreadystatechange = function () {
// XHR.readyState ==> 请求过程
// (1).请求未初始化,在open之前 --> 0
// (2).服务器连接已经建立,在open之后 --> 1
// (3).请求已经接收 --> 2
// (4).请求处理中 --> 3
// (5).请求已完成,且响应已经就绪 --> 4
// 6.处理请求结果
if (XHR.readyState === 4) {
// XHR.status 请求状态码
if (XHR.status >= 200 && XHR.status < 300) {
// 返回的是JSON格式
console.log(XHR.response);
} else {
console.log("请求失败");
}
}
}
// 7.超时处理
// 终止请求
XHR.timeout = 10000
1.4 AJAX封装
function _$(data, callback) {
// 用变量存一下属性,请求GET和POST默认转为大写
let method = data.method.toLocaleUpperCase()
let url = data.url
let params = data.params
// 如果请求方式为空,默认为 GET 请求
if (!method) {
method = "GET"
}
const XHR = new XMLHttpRequest()
// 如果为 GET 请求需要拼接路径,并且需要有参数
if (params) {
XHR.open(method, url + (method === "GET" ? `?${params}` : ""))
} else {
XHR.open(method, url)
}
// 如果为 POST 请求,设置请求头
if (method === "POST") {
// POST 请求,限制数据为json格式
XHR.setRequestHeader("Content-Type", "application/json")
// 如果有数据,发送数据
XHR.send(params ? JSON.stringify(params) : null)
} else {
XHR.send()
}
XHR.onreadystatechange = function () {
if (XHR.readyState === 4) {
if (XHR.status >= 200 && XHR.status < 300) {
callback && callback(XHR.response)
} else {
callback && callback("错误")
}
}
}
// 超时,终止请求
XHR.timeout === 10000
}
2. fetch
2.1 基本概念
- fetch 被称为下一代 AJAX 技术,采用 Promise 方式处理数据,是一种简单明了的 API
- 使用 fetch 会发送 http 请求给服务器,在不刷新网页的情况下,可以实现局部内容的更新
- 当接收到一个错误的HTTP状态码时,从 fetch() 返回的 Promise 不会返回 reject 会返回 resolve,当网络故障或请求被阻止时,才会调用 reject
2.2 GET请求案例
<!-- html部分 -->
<button>点击获取图片</button>
<img src="" alt="">
// js部分,fetch只用传入参数就可以请求数据
let btn = document.querySelector("button")
let img = document.querySelector("img")
btn.addEventListener("click", function () {
let controller = new AbortController()
// fetch 会返回一个 Promise 对象,请求默认为 GET
fetch("https://dog.ceo/api/breeds/image/random", {
signal: controller.signal
}) // 随机出一张图片的网址
.then(res => {
// 这里的res还是一个promise对象
// 需要调用json(),再次返回包含数据的promise
return res.json()
}).then(data => {
// data.status 要看后端接口的数据格式
if (data.status === "success") {
img.src = data.message
} else {
throw new Error("出错了")
}
}).catch(err => {
throw new Error(err)
})
// 取消请求
AbortController.abort()
})
2.3 POST请求案例
<!-- html部分 -->
<input type="text" value="我是要被传输的数据~~">
let input = document.querySelector("input")
input.addEventListener("click", function () {
// fetch 会返回一个 Promise 对象,默认为 GET 请求
fetch("https://xxx/xxx/xxx", {
// 它的第二个参数为一个对象,可以设置对应的配置
method: "POST",
body: JSON.stringify({ name: input.value }),
headers: {
"Content-Type": "application/json"
}
})
// 这里和GET的处理差不多
.then(res => res.json()).then(data => data).catch(err => err)
})
3. WebSocket(H5
)
3.1 基本概念
-
WebSocket 是
HTML5
开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。 -
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
3.2 WebSocket的属性和方法
3.2.1 属性
属性 | 描述 |
---|---|
Socket.readyState | 只读属性 readyState 表示连接状态,可以是以下值: 0 - 表示连接尚未建立。 1 - 表示连接已建立,可以进行通信。 2 - 表示连接正在进行关闭。 3 - 表示连接已经关闭或者连接不能打开。 |
Socket.bufferedAmount | 只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。 |
3.2.2 事件
事件 | 事件处理程序 | 描述 |
---|---|---|
open | Socket.onopen | 连接建立时触发 |
message | Socket.onmessage | 客户端接收服务端数据时触发 |
error | Socket.onerror | 通信发生错误时触发 |
close | Socket.onclose | 连接关闭时触发 |
3.2.3 方法
方法 | 描述 |
---|---|
Socket.send() | 使用连接发送数据 |
Socket.close() | 关闭连接 |
3.3 WebSocket实现聊天室
- 首页采用了两个页面,聊天室入口、聊天室,用 gulp 开启的服务,vscode 插件也可以
- 后端采用的 ws 这个库
聊天室入口部分 index.html
<!-- html文件 -->
<input type="text" placeholder="请输入用户名" id="username">
<button id="btn">进入聊天室</button>
// js文件
// 主要就是记录是哪个用户进入的聊天室
((doc, storage, location) => {
let username = doc.querySelector("#username")
let btn = doc.querySelector("#btn")
let init = () => {
bindEvent()
}
function bindEvent() {
btn.addEventListener("click", headEventBtnClick, false)
}
function headEventBtnClick() {
let usernameInfo = username.value.trim()
if (usernameInfo.length < 2) {
alert("长度不能小于2个字符")
return
}
// 输入用户名,本地存储用户名,进入聊天页
storage.setItem("username", usernameInfo)
location.href = "/chatPage.html"
}
init()
})(document, localStorage, location)
聊天室部分 chatPage.html
<!-- html文件 -->
<style>
.username {
color: red;
}
.msg {
background-color: #008c8c;
color: white;
font-weight: bold;
padding: 4px;
}
</style>
<h2></h2>
<ul id="list"></ul>
<input type="text" id="message" placeholder="请输入消息">
<button id="send">发送消息</button>
// js文件
class Demo {
constructor() {
// 确认是哪个用户的聊天室
document.querySelector("h2").innerHTML = `聊天室:${localStorage.getItem("username")}`
this.list = document.querySelector("#list")
this.msg = document.querySelector("#message")
this.sendBtn = document.querySelector("#send")
// 本地连接,端口:9527
this.ws = new WebSocket("ws:localhost:9527")
// 存用户的名字,也就是谁发送的这条消息
this.username = ""
this.init()
}
init() {
this.bindEvent()
}
bindEvent() {
// 会有 this 指向问题,用 bind 绑一下
this.sendBtn.addEventListener("click", this.sendClick.bind(this))
this.ws.addEventListener("open", this.handleOpen.bind(this))
this.ws.addEventListener("close", this.handleClose.bind(this))
this.ws.addEventListener("error", this.handleError.bind(this))
this.ws.addEventListener("message", this.handleMessage.bind(this))
}
sendClick() {
let msg = this.msg.value.trim()
// 如果为空什么都不做
if (msg.length === 0) {
return
}
// 发送数据
this.ws.send(JSON.stringify({
username: this.username,
dateTime: +new Date(),
msg
}))
this.msg.value = ""
}
handleOpen() {
// 是哪个用户发送的消息,需要知道
this.username = localStorage.getItem("username")
}
handleClose() {
console.log("ws close");
}
handleError() {
console.log("ws error");
}
// 接收后端返回的数据
handleMessage(e) {
const { username, dateTime, msg } = JSON.parse(e.data)
// 把数据结合标签添加到页面上
let li = document.createElement("li")
li.innerHTML = `
<p>用户:<span class="username">${username}</span></p>
<p>时间:${new Date(dateTime)}</p>
<p>消息:<span class="msg">${msg}</span></p>
`
this.list.appendChild(li)
}
}
new Demo()
后端部分
// 后端就随便写一下
const ws = require("ws")
// 后端与前端端口一致
const server = new ws.Server({ port: 9527 })
// 连接时触发
server.on("connection", function (ws) {
console.log("server connection");
// 接收客户端发来的数据,并广播出去(每一位连接的用户都可以接收到)
ws.on("message", function (msg) {
// 多个ws的集合
server.clients.forEach(item => {
// 传过来的是 Buffer,要转一下
item.send(msg.toString())
})
})
// 关闭时触发
ws.on("close", function (code, reason) {
console.log("close", code, reason);
});
})
聊天室效果图如下: