Ajax技术的三种实现方法

219 阅读8分钟

前言

什么是Ajax:

Ajax,全称为Asynchronous JavaAScript and XML(异步JavaScript和XML),是一种网页开发技术,它允许在不重新加载整个网页的情况下,通过JavaScript异步地从服务器获取数据并更新部分网页内容。这意味着用户可以与网页进行交互,看到内容的更新,而无需等待整个页面重新加载。

尽管名字中包含XML,现代的Ajax应用实际上可以使用各种格式交换数据,包括JSON(目前最常见), plain text,或者HTML,而不局限于XML。Ajax技术结合了JavaScript、CSS、HTML以及XMLHttpRequest对象(或其他类似的API)来向服务器请求数据,并处理来自服务器的响应。

Ajax的主要优势在于:

  • 提升用户体验:页面局部更新,无需整体刷新,使得网页响应更快,用户交互更流畅。
  • 减轻服务器负载:因为只传输需要的数据,而非整个页面,减少了带宽使用。
  • 实现动态内容更新:如实时聊天、动态加载更多内容、地图应用等交互式功能成为可能。

Ajax是Web 2.0时代的关键技术之一,极大地推动了网页应用向更丰富、更动态的方向发展。

ajax的具体操作流程:

  1. 创建 XMLHttpRequest 对象: 首先,需要在JavaScript中创建一个XMLHttpRequest对象,这是执行Ajax操作的基础。通常使用 new XMLHttpRequest() 来实例化该对象。
  2. 准备发送请求: 使用XMLHttpRequest对象的 open() 方法来初始化一个HTTP请求。这个方法接收三个参数:请求的类型(如 "GET", "POST"),请求的URL,以及一个布尔值表示是否采用异步方式发送请求(true为异步,false为同步,通常使用异步)。
  3. 设置请求头信息(可选): 如果需要,可以通过 setRequestHeader() 方法来设置HTTP请求头,比如Content-Type,这对于发送特定类型的数据(如JSON或表单数据)时可能需要。
  4. 定义响应处理函数: 设置 onreadystatechange 事件处理器,这个事件会在readyState属性值改变时触发。通常会检查 readyState 是否等于4(表示请求已完成)且 status 是否为200(表示成功响应)。在这个事件处理函数中处理从服务器接收到的数据。
  5. 发送请求: 调用XMLHttpRequest对象的 send() 方法来发送请求。如果是POST请求,需要将要发送的数据作为参数传递给 send() 方法;对于GET请求,数据通常附加在URL上,在 open() 方法中处理。
  6. 处理服务器响应: 在响应处理函数中,根据需要处理从服务器接收到的数据。这可能涉及到解析JSON、更新DOM、显示错误信息等操作,从而实现页面的局部更新。

总结起来,Ajax操作的核心流程是创建请求对象、配置请求、发送请求、监听响应并处理数据。这一系列操作使得网页能够在后台与服务器交换数据,从而提升用户体验。

readyState

代表ajax的状态,只有状态为4才可以用这份数据

0 --xhr刚创建

1 --open执行

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

3 --响应体正在解析

4 --解析完成

获取电影列表

创建一个获取电影列表的按钮,现在要实现的功能是点击按钮,可以获取到最新的电影列表,通过无序列表展示出来。点击按钮,向后端发送http请求,后端将数据接口传回给前端,通过后端来爬取电影数据,后端接口为:https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList#!method=get

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

image-20240519200900714.png 这里再给大家讲一下status什么:就是http的状态码

HTTP状态码是用以表示网页服务器HTTP响应状态的3位数字代码,它们按照类别分为五类,每个类别代表了请求处理的不同阶段或结果。下面是这些类别及其常见状态码的概述:

1xx(信息性状态码)

这类状态码表示接收的请求正在处理,需要请求者继续操作。

  • 100 Continue:表明到目前为止的请求部分是正确的,客户端应该继续发送剩余的请求。

2xx(成功状态码)

表示请求已经成功被服务器处理。

  • 200 OK:请求已成功处理,响应中包含了请求的资源。
  • 201 Created:请求成功并且服务器创建了新的资源。
  • 202 Accepted:服务器已接受请求,但尚未处理。

3xx(重定向状态码)

需要客户端进一步的操作才能完成请求。

  • 301 Moved Permanently:请求的资源已永久移动到新位置。
  • 302 Found:请求的资源临时驻留在不同的URI下,将来可能还会更改。
  • 304 Not Modified:资源未修改,可以直接使用缓存中的副本。

4xx(客户端错误状态码)

表示客户端的请求中存在错误,服务器无法处理。

  • 400 Bad Request:请求无效或无法被服务器理解。
  • 401 Unauthorized:请求要求用户的身份认证。
  • 403 Forbidden:服务器理解请求客户端的请求,但是拒绝执行此请求。
  • 404 Not Found:服务器无法找到请求的资源。

5xx(服务器错误状态码)

表示服务器在处理请求的过程中发生了错误。

  • 500 Internal Server Error:服务器遇到了不知道如何处理的情况。
  • 502 Bad Gateway:作为网关或代理工作的服务器从上游服务器收到了无效的响应。
  • 503 Service Unavailable:服务器目前无法处理请求(由于超载或停机维护)。

思路分析:通过id来获取btn这个按钮元素,并将其命名为btn,为其绑定一个监听事件,当点击该按钮的时候,触发回调函数;在用户点击按钮时,通过Ajax从指定的接口获取电影列表数据,并将这些数据以列表项的形式追加到页面的一个无序列表中,实现了动态加载内容的效果。

<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 = () => {//监听请求的过程
                //console.log(xhr.readyState);
                if (xhr.readyState == 4 && xhr.status == 200) {//拿到了后端返回的数据
                    //console.log(xhr.responseText);
                    //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元素
                        li.innerHTML = movieList[i].nm+"-----"+movieList[i].star;//设置li元素的innerHTML
                        ul.appendChild(li);//把li元素添加到ul元素中
                    }
                }
            }
        })
    </script>

代码分析:

  1. 获取页面元素

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

    • btn.addEventListener('click', ...) 为按钮添加点击事件监听器,当按钮被点击时,执行箭头函数内的代码。
  3. 创建XMLHttpRequest对象

    • let xhr = new XMLHttpRequest(); 创建一个新的XMLHttpRequest对象,用于发送Ajax请求。
  4. 配置并发送GET请求

    • xhr.open("GET", "https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList#!method=get", true); 配置请求类型为GET,指定请求的URL,以及设置请求为异步(true)。

    • xhr.send(); 发送GET请求到指定的URL。

image-20240519204248953.png

  1. 监听请求状态变化
    • xhr.onreadystatechange = () => {...} 定义一个函数,当请求状态改变时会被调用。
      • 判断请求是否完成且状态码为200 (xhr.readyState == 4 && xhr.status == 200),表示请求成功完成。
      • 使用JSON.parse(xhr.responseText)将服务器响应的文本数据转换为JavaScript对象。
      如下:

image-20240519204414066.png

  • 遍历movieList数组,对于每一个电影对象,执行以下操作:

  • 创建一个新的li元素。

  • 将电影的名称(movieList[i].nm)和评分(movieList[i].star)设置为li元素的文本内容。

  • 将这个li元素添加到ul元素中,从而在页面上显示每部电影的信息。

    最终输出结果如下:

image-20240519204520631.png

方法二:jQuery

首先要引入jquery库:

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

用Jquery方法可以更加快速的拿到movieList对象,就不用像刚刚那样每次都敲那么多行代码了,更简洁,说白了你可以理解它为一个封装类,就是一个帮你封装好了的东西,你只需要改变里面的后端请求地址就可以了,相比刚刚那个可以节省一些代码量。

<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>

这个方法前两步和上一个是一样的,主要是第三步

发起Ajax请求

  • 使用

    $.ajax({...})
    

    方法封装了Ajax请求的配置。

    • url参数指定了请求的目标地址,即电影数据的API接口。
    • method参数指定了请求的方法为"GET"。
    • data参数是一个对象,用于传递额外的数据到服务器,这里示例了传递用户名"笑笑"和年龄18,但实际上这个GET请求并不会在URL中附带这些数据,因为jQuery的data在GET请求中默认不会附加到URL。
    • success参数是一个回调函数,当请求成功时(HTTP状态码为200系列),该函数会被调用,并将服务器响应的数据作为参数res传入。

    结果:

image-20240519205754342.png

可以看到我们同样拿到了这样一个电影数组。最后在success中加上循环数组就可以实现电影列表的输出了。完整代码如下:

<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',
            data: {
                username:'笑笑',
                age:18
            },
            success: function(res) {
            const movieList = res.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>

方法三:fetch

在回调函数中,通过fetch("...") 发起一个HTTP GET请求到指定的URL(上面给出后端接口),URL中包含了查询字符串(username='椰汁'&age=18),用于传递参数,在实际应用中可能用于服务器端的某些处理或过滤;

通过.then((res) => {...}) fetch返回一个Promise,当请求成功完成时,第一个.then会被调用,传入的参数res是Response对象,代表了来自服务器的响应;

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

        btn.addEventListener("click",()=>{
            fetch("https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList?username='严总'&age=18")
            .then((res)=>{
                console.log(res);//响应体 没有被解析完全的响应体
                return res.json();
            })
            .then((data)=>{
                console.log(data);//响应体 已经被解析成json格式的数据
            })
        })
    </script>

res打印出来的是整个响应体:

image-20240519210624418.pngres.json()将响应体转换成json格式,如下所示:

image-20240519210726553.png 同样可以实现这个数组的输出。

给后端传递其他参数

法一: 在后端接口https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList上用?的方式拼接加上一个参数给后端,后端就会解析我们给的参数。例如拼接成https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList?username='笑笑'&age=18

<script>
        let btn = document.getElementById('btn');
        let ul = document.getElementById('list');
        btn.addEventListener('click',  () => {       fetch("https://mock.mengxuegu.com/mock/65a91543c4cd67421b34c898/movie/movieList?username='严总'&age=18")                      
 })
    </script>

在电脑的检查网络中的载荷中就可以看到我们传入的参数了 image-20240519211219846.png 法二:用jquery方法,在其中的$.ajax({}) 里面加上data

 <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',
            data: {
                username:'严总',
                age:18
            }
        })
      })
    </script>

三种方法相比较:

1.XMLHttpRequest:经典的实现方式,通过创建请求实例、配置请求参数、发送请求、监听状态变化,直至处理响应数据,步步为营,手动控制请求的全过程。

2.jQuery的$.ajax():简化了操作,提供了一套链式调用接口,让发送请求和处理响应变得直观易懂,尤其适合习惯jQuery框架的开发者。

3.Fetch API:现代浏览器的原生支持,基于Promise设计,代码更为简洁优雅,支持async/await语法,更符合现代JavaScript编程风格。