阿贾克斯武器大师的前后端桥梁

349 阅读4分钟

相信很多前端工程师都玩过英雄联盟,无一例外我曾经也是英雄联盟的狂热粉丝,想当年也是凭借一手塔姆舔天舔地,舔上了小学生之手的超凡大师。后来无意间看了一部电影,相信在看这篇文章的很多男人都看过,也就是1972年发布的电影《教父》。让我从浑浑噩噩的大学时光重新掌握了学习的节奏,记得刚打英雄联盟那会,最喜欢玩的两个英雄,一个就是蛮王,一个就是阿贾克斯。当时打游戏玩的菜,天天被虐还是爱玩,现在AJAX就算虐我一万遍我也要硬着头皮学完,别人能学会的我也能学会,我会比别人差嘛!!!



一、Ajax是什么

  • Ajax全称为Asynchronous JavaScript And XML,即异步 JavaScript 和 XML 技术,这是前后端沟通的一种重要机制。

Ajax是一种异步无刷新技术,现在大部分的请求都是基于同步,也就是大多数请求发送出去之后必须等待请求返回结果才能继续往下操作。异步就是无需等待服务器返回结果,我们就可以继续做别的事情。通过无刷新技术结合DOM操作,Ajax一般用于局部刷新或者无刷新。今天主要来了解前后端的桥梁是如何构建起来的,让我们开始今天的学习历程吧。


二、前端页面DEMO

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div>
      <input type="text" id="username" />
      <input type="text" id="password" />
      <button id="btn">登录</button>
    </div>
  </body>
</html>

image.png

可以看到页面的展示效果,让我们来画张流程图来看看前端和后端交互的过程,数据库存在的意义就是为了让我们能去高效的查找数据。当登录成功之后发生页面跳转或者页面提示登录成功都是可以的,实现页面与后端的交互。

image.png

现在最关键的问题就是客户端如何将abc 123发送给后端,前端的代码当中一定要有传送http请求出去。现在让我们开始写下后端的请求接口。



三、歌手请求数据

xhr是个对象,身上还有很多属性和方法可以使用,这些方法都是在xhr的原型上面,让前端朝着地址请求。

const xhr = new XMLHttpRequest() // 创建异步对象

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <button id="btn">获取歌手信息</button>
    <div id="app"></div>

    <script>
      let btn = document.getElementById("btn");
      btn.addEventListener("click", () => {
        // 获取歌手数据
        getData();
      });

      function getData() {
        const xhr = new XMLHttpRequest(); // 创建异步对象
        xhr.open(
          "GET",
          "https://mock.mengxuegu.com/mock/66585c4db462b81cb3916d3e/songer/songer",
          true // 声明成异步代码
        );
        xhr.send(); // 发送请求
        // 监测请求的发送结果
        xhr.onreadystatechange = function () {
          if (xhr.readyState === 4 && xhr.status === 200) {
            // 请求成功
            console.log(xhr.responseText);
          }
        };
      }
    </script>
  </body>
</html>

当写完上述代码之后就可以看到请求的效果了,现在都为字符串不好操作,有没有方法处理数据呢 image.png

        xhr.onreadystatechange = function () {
          if (xhr.readyState === 4 && xhr.status === 200) {
            // 请求成功
            let data = JSON.parse(xhr.responseText); // 把 json 字符串转换为 json 对象
            console.log(data);
          }
        };

现在只需要将拿到的数据写上代码,将json字符串转换为json对象。上述代码每次写是不是觉得代码太繁琐了呢,没错官方封装了新的方法给我们来使用。

image.png


四、fetch

    <script>
      // 提示:脚本放在头部会阻塞页面渲染,不推荐这样做;而使用 window.onload 又会有点晚
      // 监听 DOMContentLoaded 事件,当 HTML 文档解析完成后执行回调函数
      document.addEventListener("DOMContentLoaded", async () => {
        // console.log(document.getElementById("repos"));
        // 提示:使用 async/await 可以让异步代码看起来像同步代码
        // es8 async await
        // await 后面需要接一个 Promise 实例
        // new Promise Promise {} fetch 本质是返回一个 Promise 实例
        // new Promise 实例有三种状态:pending(等待)、fulfilled(完成)、rejected(失败)
        
        // 打印 fetch 请求返回的 Promise 实例,用于调试
        console.log(fetch("https://api.github.com/users/shunwuyu/repos"));
        
        // 使用 await 关键字等待 fetch 请求完成,获取响应结果
        const result = await fetch(
          "https://api.github.com/users/shunwuyu/repos"
        );
        // 等待响应数据解析为 JSON 格式
        const data = await result.json();
        // 打印解析后的数据,可用于调试,当前代码已注释掉
        // console.log(data);
        // 将获取到的数据中的仓库名渲染到页面的 repos 列表中
        document.getElementById("repos").innerHTML = data
          .map((item) => `<li>${item.name}</li>`)
          .join("");
      });
    </script>
  </head>
  <body>
    <!-- 定义一个无序列表,用于展示获取到的仓库名 -->
    <ul id="repos"></ul>
    <script>
      // 再次监听 DOMContentLoaded 事件,打印 repos 元素,可用于调试
      document.addEventListener("DOMContentLoaded", () => {
        console.log(document.getElementById("repos"));
      });
    </script>

fetch 是现代浏览器提供的一个用于发起网络请求的 API,基于 Promise 实现。在这段代码里,fetch 关键字用于发起一个 GET 请求。以下是具体解释:

  1. fetch 接收一个 URL 作为参数,代码中请求的是 https://mock.mengxuegu.com/mock/66585c4db462b81cb3916d3e/songer/songer
  2. fetch 返回一个 Promise,这个 Promise 会在请求收到响应时被解析。
  3. 使用 .then((res) => res.json()) 将响应数据解析为 JSON 格式。
  4. 再次使用 .then((data) => { console.log(data); }) 处理解析后的数据,将其打印到控制台。

整体来看,这段代码借助 fetch API 从指定接口获取数据,并将返回的 JSON 数据打印到控制台。

五、fetch和XHR怎么选?

  • 新项目、喜欢简洁就用fetch
  • 老项目、要兼容IE就用XHR

其实大多数时候,fetch已经能满足绝大部分需求了。