XHR 的理解和使用-使用XHR封装ajax请求参数

MDN文档

https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest

理解

  1. 使用 XMLHttpRequest (XHR)对象可以与服务器交互, 也就是发送 ajax 请求
  2. 前端可以获取到数据,而无需让整个的页面刷新。
  3. 这使得 Web 页面可以只更新页面的局部,而不影响用户的操作。

区别一般 http 请求与 ajax 请求

  1. ajax 请求是一种特别的 http 请求
  2. 对服务器端来说, 没有任何区别, 区别在浏览器端
  3. 浏览器端发请求: 只有 XHR 或 fetch 发出的才是 ajax 请求, 其它所有的都是
    非 ajax 请求
  4. 浏览器端接收到响应
    (1) 一般请求: 浏览器一般会直接显示响应体数据, 也就是我们常说的刷新/
    跳转页面
    (2) ajax 请求: 浏览器不会对界面进行任何更新操作, 只是调用监视的回调
    函数并传入响应相关数据

API

  1. XMLHttpRequest(): 创建 XHR 对象的构造函数
  2. status: 响应状态码值, 比如 200, 404
  3. statusText: 响应状态文本
  4. readyState: 标识请求状态的只读属性
    0: 初始
    1: open()之后
    2: send()之后
    3: 请求中
    4: 请求完成
  5. onreadystatechange: 绑定 readyState 改变的监听
  6. responseType: 指定响应数据类型, 如果是’json’, 得到响应后自动解析响应
    体数据
  7. response: 响应体数据, 类型取决于 responseType 的指定
  8. timeout: 指定请求超时时间, 默认为 0 代表没有限制
  9. ontimeout: 绑定超时的监听
  10. onerror: 绑定请求网络错误的监听
  11. open(): 初始化一个请求, 参数为: (method, url[, async])
  12. send(data): 发送请求
  13. abort(): 中断请求
  14. getResponseHeader(name): 获取指定名称的响应头值
  15. getAllResponseHeaders(): 获取所有响应头组成的字符串
  16. setRequestHeader(name, value): 设置请求头

XHR 的 ajax 封装

  1. 函数的返回值为 promise, 成功的结果为 response, 异常的结果为 error
  2. 能处理多种类型的请求: GET/POST/PUT/DELETE
  3. 函数的参数为一个配置对象
    {
    url: ‘’, // 请求地址
    method: ‘’, // 请求方式 GET/POST/PUT/DELETE
    params: {}, // GET/DELETE 请求的 query 参数
    data: {}, // POST 或 DELETE 请求的请求体参数
    }
  4. 响应 json 数据自动解析为 js
    代码实现:
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>

  <body>
    <div>
      <button onclick="testGet()">GET 请求</button>
      <button onclick="testPost()">POST 请求</button>
      <button onclick="testPut()">PUT 请求</button>
      <button onclick="testDelete()">DELETE 请求</button>
    </div>
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.24.0/axios.js"></script>
    <script>
      /*
  使用 XHR 封装发送 ajax 请求的通用函数
  返回值: promise
  参数为配置对象
  url: 请求地址
  params: 包含所有 query 请求参数的对象 {name: tom, age: 12} ==> name=tom&age=12
  data: 包含所有请求体参数数据的对象
  method: 为请求方式
  */
      function axios({ url, method = "GET", params = {}, data = {} }) {
        // 返回一个promise对象
        return new Promise((resolve, reject) => {
          // 处理method(转大写)
          method = method.toUpperCase();

          // 处理query参数(拼接到url上)   id=1&xxx=abc
          /* 
        {
          id: 1,
          xxx: 'abc'
        }
        */
          let queryString = "";
          Object.keys(params).forEach((key) => {
            // queryString += `${key}=${params[key]}&`;
            queryString += key + "=" + params[key] + "&";
          });
          if (queryString) {
            // id=1&xxx=abc&
            // 去除最后的&
            queryString = queryString.substring(0, queryString.length - 1);
            // 接到url
            url += "?" + queryString;
          }

          // 1. 执行异步ajax请求
          // 创建xhr对象
          const request = new XMLHttpRequest();
          // 打开连接(初始化请求, 没有请求)
          request.open(method, url, true);

          // 发送请求
          if (method === "GET" || method === "DELETE") {
            request.send();
          } else if (method === "POST" || method === "PUT") {
            request.setRequestHeader(
              "Content-Type",
              "application/json;charset=utf-8"
            ); // 告诉服务器请求体的格式是json
            request.send(JSON.stringify(data)); // 发送json格式请求体参数
          }

          // 绑定状态改变的监听
          request.onreadystatechange = function () {
            // 如果请求没有完成, 直接结束
            if (request.readyState !== 4) {
              return;
            }
            // 如果响应状态码在[200, 300)之间代表成功, 否则失败
            const { status, statusText } = request;
            // 2.1. 如果请求成功了, 调用resolve()
            if (status >= 200 && status <= 299) {
              // 准备结果数据对象response
              const response = {
                data: JSON.parse(request.response),
                status,
                statusText,
              };
              resolve(response);
            } else {
              // 2.2. 如果请求失败了, 调用reject()
              reject(new Error("request error status is " + status));
            }
          };
        });
      }
      function testGet() {
        axios({
          url: "http://localhost:3000/comments",
          // url: 'http://localhost:3000/comments2',
          params: { id: 3 },
        })
          .then((response) => {
            console.log("get success", response.data, response);
          })
          .catch((err) => {
            alert(err.message);
          });
      }
      function testPost() {
        axios({
          url: "http://localhost:3000/comments",
          // url: 'http://localhost:3000/comments2',
          method: "POST",
          data: { body: "aaaa", postId: 2 },
        })
          .then((response) => {
            console.log("post success", response.data, response);
          })
          .catch((error) => {
            alert(error.message);
          });
      }
      function testPut() {
        axios({
          url: "http://localhost:3000/comments/3",
          method: "put",
          data: { body: "ndkasj", postId: 2 },
        })
          .then((res) => {
            console.log("put success", res.data, res);
          })
          .catch((err) => {
            alert(err.message);
          });
      }
      function testDelete() {
        axios({
          url: "http://localhost:3000/comments/1",
          method: "delete",
          params: {
            body: "some comment",
          },
        })
          .then((response) => {
            console.log("delete success", response.data, response);
          })
          .catch((error) => {
            alert(error.message);
          });
      }
    </script>
  </body>
</html>

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值