当前位置:   article > 正文

网络 AJAX、Fetch、WebSocket的基本认识(分享)_fetch和ajax

fetch和ajax

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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
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
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

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="">
  • 1
  • 2
  • 3
// 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()
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
2.3 POST请求案例
<!-- html部分 -->
<input type="text" value="我是要被传输的数据~~">
  • 1
  • 2
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)
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

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 事件
事件事件处理程序描述
openSocket.onopen连接建立时触发
messageSocket.onmessage客户端接收服务端数据时触发
errorSocket.onerror通信发生错误时触发
closeSocket.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>
  • 1
  • 2
  • 3
// 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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

聊天室部分 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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
// 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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72

后端部分

// 后端就随便写一下
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);
  });
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

聊天室效果图如下:
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/148386?site
推荐阅读
相关标签
  

闽ICP备14008679号