一分钟搞定用Ajax实现前后端相互交流

531 阅读9分钟

作者:江财第一深情(宇)

引言

今天,我们聊的是在javaScript中,如何用Ajax来向后端发出请求,实现前后端相互交流。相信有很多小伙伴们经常会遇到这样一种情况,当你第一次使用某种app时候,会让你注册一个账号,在这之前,需要填写一些信息。常见的:填写电话号码,然后点击获取一个验证码。那么这个验证码从何而来?其实这里有一个执行一个过程,当你点击获取验证码的时候,会向后端发送一个请求,然后后端返回一个数据到用户。那么,在javaScript,我们怎么向后端发送请求呢,让我们一起来探索一下吧!

什么是Ajax(定义)

Ajax,全称为Asynchronous JavaScript and XML(异步JavaScript与XML),是一种网页开发技术,它能够让网页无须刷新就能与服务器交换数据并更新部分内容。这意味着用户可以享受到更快、更流畅的网页体验,因为只有需要更新的数据会被请求和交换,而不是重新加载整个页面。

Ajax的工作流程

  1. 创建XMLHttpRequest对象:这是Ajax的核心组件,用于在后台与服务器交换数据。所有现代浏览器均内建了 XMLHttpRequest 对象。
Javascript
1var xhr = new XMLHttpRequest();
  1. 配置请求:在发送请求之前,需要设置请求的方法(GET、POST等)、URL以及是否异步执行等。
Javascript
1xhr.open('GET', 'example.php', true);
  1. 设置回调函数:使用onreadystatechange事件监听请求状态的变化。当请求完成且状态为200(表示成功)时,执行相应的处理函数。
Javascript
1xhr.onreadystatechange = function() {
2    if (xhr.readyState == 4 && xhr.status == 200) {
3        // 在这里处理服务器返回的数据
4        console.log(xhr.responseText);
5    }
6};
  1. 发送请求:调用send()方法发送请求。如果是POST请求,还需要将数据作为参数传递给该方法。
Javascript
1xhr.send(null); // 对于GET请求,直接发送null
2// 或者 xhr.send('param1=value1&param2=value2'); // 对于POST请求

5.最后, 客户端收到响应数据后,在回调函数中处理这些数据,如更新DOM,从而实现页面的局部刷新。**

那么问题来了,为什么在代码中,突然跑出来 '4'和 '200'这两个数字呢,这两个数字有什么特殊的含义呢?

首先,我们要知道xhr.readyStatexhr.status, xhr.readyState是 XMLHttpRequest(XHR)对象的一个属性,用于表示当前 AJAX 请求的生命周期中的不同状态

1 -- open执行

2 -- 请求发送出去,响应头被接受

3 -- 响应体正在解析

4 -- 解析完成

xhr.status 是 XMLHttpRequest(XHR)对象的另一个属性,用于表示服务器对请求所返回的HTTP状态码,当xhr.status==200时,表示请求已成功处理。

所以‘4’ 和‘200’这两个数字不是凭空而来的

接下来,我们用Ajax的三种方法,实现一个获取电影列表的案例

第一种,用原生的XMLHttpRequest

<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>
    <ul id="list">
       <li></li>
    </ul>

这个是一个简单的html结构,- <button id="btn">获取电影列表</button>: 创建了一个按钮,文本为"获取电影列表"。id="btn" 为按钮分配了一个唯一的标识符,便于通过JavaScript来选择和操控这个元素。-
<li></li>: 无序列表中的一个列表项(List Item)。在这个例子中,列表项是空的,预期通过JavaScript动态添加电影条目。 接下来我们来看JavaScript片段


 <script>
         let btn=document.getElementById('btn')
         let ul=document.getElementById("list")
         btn.addEventListener('click',()=>{
             //朝一个接口发请求,获取到数据展示在页面上
             let xhr=new XMLHttpRequest();  //创建一个ajax实例
             xhr.open('GET','https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList#!method=get',true)                //配置发送的参数
             xhr.send();
             xhr.onreadystatechange = () =>{    //监听请求的过程
                if(xhr.readyState ==4&&xhr.status==200){    //拿到了后端返回的数据
                   console.log(JSON.parse(xhr.responseText))
                   //展示在页面上
                   const movieList= JSON.parse(xhr.responseText).movieList
                   console.log(movieList);
                   for(let i=0; i<movieList.length;i++)
                   {
                      const li=document.createElement("li");
                      li.innerHTML=movieList[i].nm + "--" +movieList[i].star
                      ul.appendChild(li)
                       // movieList[i]

                   }
                } 
             }
         })
    </script>

来解释一下这段代码

  1. 获取页面上的元素:

    • let btn = document.getElementById('btn') 获取id为"btn"的按钮元素。
    • let ul = document.getElementById("list") 获取id为"list"的无序列表元素。
  2. 给按钮绑定点击事件监听器:

    • btn.addEventListener('click', ()=>{...}) 当按钮被点击时,执行匿名箭头函数内的代码。
  3. 发起Ajax GET请求:

  • let xhr = new XMLHttpRequest() 创建一个新的XMLHttpRequest对象,用于发送Ajax请求。 - xhr.open('GET', 'https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList#!method=get', true) 配置请求,指定请求方法为GET,请求的URL,以及请求是否异步(true表示异步)。
  • xhr.send() 发送请求到服务器。
  1. 监听请求状态变化并处理响应:
  • xhr.onreadystatechange = ()=>{...} 设置一个事件处理器,当请求状态改变时执行。

  • if(xhr.readyState == 4 && xhr.status == 200) 判断请求是否完成(readyState == 4)且服务器响应成功(status == 200)。

    • console.log(JSON.parse(xhr.responseText))` 打印出服务器返回的原始JSON格式的响应数据。
  • 解析响应数据并遍历电影列表:

  • const movieList = JSON.parse(xhr.responseText).movieList 将响应的JSON字符串转换为JavaScript对象,并提取出movieList数组。

  • 使用for循环遍历movieList数组:

  • const li = document.createElement("li") 为每部电影创建一个新的<li>元素。

  • li.innerHTML = movieList[i].nm + "--" + movieList[i].star 设置<li>的内容为电影名称(nm)和演员(star)。

  • ul.appendChild(li) 将新创建的<li>元素添加到无序列表(ul)中。

最后展示一下效果 eb953c36cb075d0240f27eb4664db04.png 每当点击获取电影列表时,页面都会展示相关电影的信息

第二种,用jQuery

首先,我们需要导入jQuery库

 <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>

下面是js代码



<button id="btn">徐宇点击按钮获取电影列表</button>
    <ul id="list">
        <li></li>
    </ul>
    <script>
        let btn = document.getElementById('btn')
        let ul = document.getElementById("list")
            btn.addEventListener('click', () => {
                 $.ajax({
                        url:'https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList#!method=get',
                        method:'GET',
                        data:{
                              username:'徐宇',
                              age:18
                        },
                        success:function(res)
                        {
                            console.log(res)
                        }

                 })
            })

    </script>

来解释一下这段代码

  • btn.addEventListener('click', () => {...}): 为按钮添加了一个点击事件监听器。当按钮被点击时,执行括号内的匿名箭头函数。

  • 在匿名函数内部,使用了jQuery的$.ajax方法来发起一个Ajax请求:

    • url: 'https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList#!method=get': 指定了Ajax请求的目标URL,这是一个模拟的电影列表API。
    • method: 'GET': 指定请求的方法为GET。
    • data: {username: '牛哥', age: 18}: 发送到服务器的额外数据,虽然在这个上下文中API可能并不需要这些数据,但这里展示了如何携带数据。
    • success: function(res) {console.log(res)}: 成功获取到服务器响应时执行的函数,这里的res是服务器返回的数据。当前示例中只是简单地将响应打印到控制台。

相比上一次那一种方法,这种是不是简单一点呢?但是现实生活中,我们不仅要获取到后端的数据,一般情况下,前端也需要向后端发送一个或者多个参数,所以,这两个方法显得不是很优雅。那么下面,我们再来介绍另外一种方法

fetch

<body>
    <button id="btn">fetch获取电影列表</button>
    <ul id="list"></ul>

    <script>
        let btn = document.getElementById('btn');
        let ul = document.getElementById('list');

        // 给按钮添加点击事件监听器
        btn.addEventListener('click', () => {
            // 使用 fetch API 发送 GET 请求
            fetch("https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList?username='牛哥'&age=18")
            .then((res) => {
                // 当请求成功后,返回响应对象并将其解析为 JSON 格式
                return res.json();
            })
            .then((data) => {
                // 在第二个 then 中处理解析后的 JSON 数据
                // console.log(data);
                const movieList = data.movieList;
                for (let i = 0; i < movieList.length; i++) {
                     const li = document.createElement('li');
                     li.innerText = movieList[i].nm + '--' + movieList[i].star;
                     ul.appendChild(li);
                 }
            })
        })
    </script>
</body>

来解释一下这段代码

  1. 获取页面元素:

    • let btn = document.getElementById('btn') 获取ID为"btn"的按钮元素。
    • let ul = document.getElementById('list') 获取ID为"list"的无序列表元素。
  2. 添加点击事件监听器:

    • btn.addEventListener('click', () => {...}) 为按钮添加点击事件监听器,当按钮被点击时,执行匿名箭头函数内的代码。
  3. 发起网络请求:

    • 使用fetch函数发送一个GET请求到指定的URL (https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList),尝试携带查询参数 (username='牛哥'&age=18)。注意,根据API的实际需求,这些查询参数可能并不必要或格式不正确,应根据API文档调整。
  4. 处理响应:

    • .then((res) => {...}) 第一个.then处理fetch返回的Promise,其中res是响应对象。

      • return res.json() 将响应体解析为JSON格式。此方法返回一个新的Promise,允许链式调用下一个.then
  5. 处理数据并更新DOM:

    • 第二个.then((data) => {...}) 在数据解析成功后执行,data是解析后的JSON对象。

      • const movieList = data.movieList; 从响应数据中提取电影列表。
      • 使用for循环遍历movieList,为每个电影创建一个新的<li>元素,并将其文本内容设置为电影的名字和演员信息。
      • ul.appendChild(li); 将新创建的<li>元素添加到ul元素中,实现电影列表的动态渲染。

在这里,我们可以在fetch里面,向后端传一些参数

 fetch("https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList?username='牛哥'&age=18")

仔细看这段代码,传参数的语法是:

1.在地址的最后面,写一个 (问号),

2.然后写 参数名字:"你想要向后端传入的值" 如上面username="牛哥"

3.假如你想向后端传入多个参数,直接用&进行连接

那么,怎么知道向后端发送的参数有没有成功呢?我们在控制台里面点击网络,如果点击触发事件之后,吹出现了一个负载,并且参数的数据对了,说明发送成功了

5eb072194cf8be6684940ca2cbf8ed3.png

最后,总结一下这三种方法的优缺点

XMLHttpRequest (XHR)

优点:

  • 原生支持: 作为最早支持Ajax的原生JavaScript对象,几乎所有现代浏览器都支持。
  • 广泛兼容: 支持多种请求类型(GET、POST、PUT、DELETE等)和多种数据格式。
  • 灵活性高: 提供详细的请求和响应控制,包括设置请求头、超时、取消请求等。

缺点:

  • 代码繁琐: 相比于Fetch和jQuery,编写XMLHttpRequest的代码较为冗长,需要手动处理各种状态和事件。
  • 回调地狱: 异步处理依赖回调函数,可能导致代码难以理解和维护。

jQuery的Ajax方法

优点:

  • 简化语法: 提供了更简洁的API,相比原生XHR减少了大量样板代码。
  • 跨域支持: 自动处理跨域请求的CORS头部,简化跨源通信。
  • 链式调用: 结合jQuery的链式操作,使得代码更易读。
  • 强大的错误处理: 内置了良好的错误处理机制。

缺点:

  • 库依赖: 需要引入整个jQuery库,即使你只需要使用Ajax功能,这可能增加页面体积。
  • 过时风险: 随着现代前端框架和库的兴起,jQuery的使用逐渐减少。

Fetch API

优点:

  • 现代化: 基于Promise,支持async/await,使得异步编程更加优雅和易于理解。
  • 原生支持: 无需第三方库,现代浏览器均支持。
  • 流式处理: 支持Response对象的Body作为ReadableStream,适用于处理大文件或实时数据。

缺点:

  • 不支持老浏览器: IE不支持,对于需要兼容老旧浏览器的应用需要polyfill。
  • 错误处理: 默认情况下,即使是404或500等HTTP错误也会当作成功处理,需要手动检查response.ok或使用try/catch来捕获错误。
  • 缺少进度和超时选项: 不像XHR,Fetch原生不支持进度事件和超时设置。

总结

今天,我们了解了在js中,介绍了3种方法,如何向后端发送请求,并实现了一个获取电影列表的案例,并且分析了3种方法的优缺点。如果您觉得在这里,能获取到知识,希望多多支持一下