深度剖析Ajax实现方式(原生框架、JQuery、Axios,Fetch)

Ajax学习

简介:

​ Ajax 代表异步 JavaScript 和 XML(Asynchronous JavaScript and XML)的缩写。它指的是一种在网页开发中使用的技术,通过在后台与服务器进行数据交换,实现页面内容的更新,而无需刷新整个页面。Ajax 技术可以使网页更加动态和交互性,提供更好的用户体验。

场景:

  • 页面懒加载
  • 登录注册相关提示
  • 鼠标移上去才加载

XML:

​ XML (eXtensible Markup Language) 是一种用于描述数据的标记语言。它被设计用于传输和存储数据,同时具有跨平台和跨应用程序的特性。XML 使用标记来标识和组织数据,类似于 HTML,但不同于 HTML,XML 的目标是描述数据,传输数据而不是展示数据。

xml 复制代码
<student>
<name>孙悟空</name>
<age>18</age>
<gender>男</gender>
</student>
xml 复制代码
<person>
  <name>John Doe</name>
  <age>30</age>
  <email>john.doe@example.com</email>
</person>

JSON:

​ JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式。它基于 JavaScript 的语法,但已成为一种独立于编程语言的通用数据格式。JSON 使用易于阅读和编写的文本格式,用于表示结构化的数据。

json 复制代码
{"name":"孙悟空","age":18,"gender":"男"}
json 复制代码
{
  "name": "John Doe",
  "age": 30,
  "email": "john.doe@example.com",
  "hobbies": ["reading", "traveling", "photography"],
  "address": {
    "street": "123 Main St",
    "city": "Exampleville",
    "country": "USA"
  }
}

服务端框架:

​ 因为Ajax的学习需要与服务器端进行交互,为了学习方便,我们采用express框架作为服务器端。

​ 官网:Express/Node 入门 - 学习 Web 开发 | MDN (mozilla.org)

环境安装:

复制代码
npm init --yes
npm i express //相当于npm install express

express的基本使用

js 复制代码
//1. 引入express
const express = require('express');
//2. 创建应用对象
const app = express();

//3. 创建路由规则
// request 是对请求 response是响应
// 当访问跟路由的时候向reponse发送数据
app.get('/', (request, response)=>{
    //设置响应数据
    response.send('HELLO EXPRESS');
});

//4. 监听端口启动服务
app.listen(8000, ()=>{
    console.log("服务已经启动, 8000 端口监听中....");
});

原生框架:

get请求:
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AJAX GET 请求</title>
    <style>
        #result{
            width:200px;
            height:100px;
            border:solid 1px #90b;
        }
    </style>
</head>
<body>
    <button>点击发送请求</button>
    <div id="result"></div>

    <script>
        //获取button元素
        const btn = document.getElementsByTagName('button')[0];
        const result = document.getElementById("result");
        // 对按钮绑定点击事件 
        btn.onclick = function(){
            //1. 创建对象
            const xhr = new XMLHttpRequest();
            //2. 初始化 设置请求方法和 url
            xhr.open('GET', 'http://127.0.0.1:8000/server?a=100&b=200&c=300');
            //3. 发送
            xhr.send();
            //4. 事件绑定 处理服务端返回的结果
            xhr.onreadystatechange = function(){
                //判断 (服务端返回了所有的结果)
                if(xhr.readyState === 4){
                    // 2xx 成功
                    if(xhr.status >= 200 && xhr.status < 300){
                        //响应 
                        console.log(xhr.status);//状态码 200
                        console.log(xhr.statusText);//状态字符串 OK?
                        console.log(xhr.getAllResponseHeaders());//所有响应头
                        console.log(xhr.response);//响应体
                    
                        //设置 result 的文本
                        result.innerHTML = xhr.response;
                    }else{

                    }
                }
            }


        }
    </script>
</body>
</html>

后台服务器,服务器是用express框架搭建起来的本地服务器。

js 复制代码
//1. 引入express
const express = require('express');

//2. 创建应用对象
const app = express();
app.get('/', (request, response) => {
    //设置响应
    response.send('HELLO EXPRESS');
  });
//3. 创建路由规则
// app.get 是get请求 
app.get('/server', (request, response) => {
    //设置响应头  设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    //设置响应体
    response.send('HELLO AJAX - 2');
});

我们看一下点击后的结果:

post请求:
html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AJAX POST 请求</title>
    <style>
        #result {
            width: 200px;
            height: 100px;
            border: solid 1px #bfa;
        }
    </style>
</head>

<body>
    <div id="result"></div>
    <script>
        //获取元素对象
        const result = document.getElementById("result");
        //绑定事件 对普通元素的绑定 
        //DOM2的方式 mouseover 鼠标移上去 
        result.addEventListener("mouseover", function () {
            //1. 创建对象
            const xhr = new XMLHttpRequest();
            //2. 初始化 设置类型与 URL
            xhr.open('POST', 'http://127.0.0.1:8000/server');
            //3. 发送
            xhr.send('a=100&b=200&c=300');
            //4. 事件绑定
            xhr.onreadystatechange = function () {
                //判断
                if (xhr.readyState === 4) {
                    if (xhr.status >= 200 && xhr.status < 300) {
                        //处理服务端返回的结果
                        result.innerHTML = xhr.response;
                    }
                }
            }
        });
    </script>
</body>

</html>
js 复制代码
//1. 引入express
const express = require('express');

//2. 创建应用对象
const app = express();
app.get('/', (request, response) => {
    //设置响应
    response.send('HELLO EXPRESS');
});

app.post('/server', (request, response) => {
    //设置响应头  设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    //设置响应体
    response.send('HELLO AJAX - 2 post');
});
请求头:

下面我们看下如何设置请求头参数:

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AJAX POST 请求</title>
    <style>
        #result {
            width: 200px;
            height: 100px;
            border: solid 1px #bfa;
        }
    </style>
</head>

<body>
    <div id="result"></div>
    <script>
        const result = document.getElementById("result");
        result.addEventListener("mouseover", function () {
            //1. 创建对象
            const xhr = new XMLHttpRequest();
            //2. 初始化 设置类型与 URL
            xhr.open('POST', 'http://127.0.0.1:8000/server');
            //设置请求头
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            //Content-Type 设置请求体类型 
            //application/x-www-form-urlencoded  参数查询字符串的类型
            //3. 发送
            xhr.send('a=100&b=200&c=300');
  
            xhr.onreadystatechange = function () {
                //判断
                if (xhr.readyState === 4) {
                    if (xhr.status >= 200 && xhr.status < 300) {
                        //处理服务端返回的结果
                        result.innerHTML = xhr.response;
                    }
                }
            }
        });
    </script>
</body>

</html>
自定义请求头:
html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AJAX POST 请求</title>
    <style>
        #result {
            width: 200px;
            height: 100px;
            border: solid 1px #bfa;
        }
    </style>
</head>

<body>
    <div id="result"></div>
    <script>
        //获取元素对象
        const result = document.getElementById("result");
        result.addEventListener("mouseover", function () {
            const xhr = new XMLHttpRequest();
            xhr.open('POST', 'http://127.0.0.1:8000/server');
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            xhr.setRequestHeader('name', 'demo');
            //3. 发送
            xhr.send('a=100&b=200&c=300');
            // xhr.send();

            //4. 事件绑定
            xhr.onreadystatechange = function () {
                //判断
                if (xhr.readyState === 4) {
                    if (xhr.status >= 200 && xhr.status < 300) {
                        //处理服务端返回的结果
                        result.innerHTML = xhr.response;
                    }
                }
            }
        });
    </script>
</body>

</html>
js 复制代码
//可以接收任意类型的请求 
app.all('/server', (request, response) => {
    //设置响应头  设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    //响应头
    response.setHeader('Access-Control-Allow-Headers', '*');
    //设置响应体
    response.send('HELLO AJAX POST');
});
JSON:

​ 有一个问题,在ajax中后台只能给前台传递字符串,但是json对象是一个键值对形式的对象,我们不能传递对象,所以在服务器端需要使用 JSON.stringify() 将json对象专户为json字符串,这样就可以发送了。同样的我们前端对后端传递过来的json字符串,需要重新转化为json对象,调用JSON.parse() 这个方法。

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JSON响应</title>
    <style>
        #result{
            width:200px;
            height:100px;
            border:solid 1px #89b;
        }
    </style>
</head>
<body>
    <div id="result"></div>
    <script>
        const result = document.getElementById('result');
        //绑定键盘按下事件
        window.onkeydown = function(){
            const xhr = new XMLHttpRequest();
            xhr.responseType = 'json';  //自动处理
            xhr.open('GET','http://127.0.0.1:8000/json-server');
            xhr.send();
            xhr.onreadystatechange = function(){
                if(xhr.readyState === 4){
                    if(xhr.status >= 200 && xhr.status < 300){
                        // 1. 手动对数据转化
                        // let data = JSON.parse(xhr.response);
                        // result.innerHTML = data.name;
                        // 2. 自动转换     
                        result.innerHTML = xhr.response.name;
                    }
                }
            }
        }
    </script>
</body>
</html>
js 复制代码
app.all('/json-server', (request, response) => {
    //设置响应头  设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    //响应头
    response.setHeader('Access-Control-Allow-Headers', '*');
    const data = {
        name: 'demo'
    };
    //对对象进行字符串转换
    let str = JSON.stringify(data);
    //设置响应体
    response.send(str);
});
复制代码
nodemon.cmd .\server.js
请求超时控制:

js中定时器的实现:

js 复制代码
    setTimeout(() => {
        response.send('延时响应');
    }, 1000) //1000代表1000毫秒 即1秒
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>请求超时与网络异常</title>
    <style>
        #result{
            width:200px;
            height:100px;
            border:solid 1px #90b;
        }
    </style>
</head>
<body>
    <button>点击发送请求</button>
    <div id="result"></div>
    <script>
        // 根据标签名 
        const btn = document.getElementsByTagName('button')[0];
        //根据css选择器 
        const result = document.querySelector('#result');
        btn.addEventListener('click', function(){
            const xhr = new XMLHttpRequest();
            //超时设置 2s 设置
            xhr.timeout = 2000;
            //超时回调
            xhr.ontimeout = function(){
                alert("网络异常, 请稍后重试!!");
            }
            //网络异常回调
            xhr.onerror = function(){
                alert("你的网络似乎出了一些问题!");
            }
            xhr.open("GET",'http://127.0.0.1:8000/delay');
            xhr.send();
            xhr.onreadystatechange = function(){
                if(xhr.readyState === 4){
                    if(xhr.status >= 200 && xhr.status< 300){
                        result.innerHTML = xhr.response;
                    }
                }
            }
        })
    </script>
</body>
</html>
js 复制代码
//延时响应
app.all('/delay', (request, response) => {
    response.setHeader('Access-Control-Allow-Origin', '*');
    response.setHeader('Access-Control-Allow-Headers', '*');
    setTimeout(() => {
        response.send('延时响应');
    }, 1000)
});
请求取消:
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>取消请求</title>
</head>
<body>
    <button>点击发送</button>
    <button>点击取消</button>
    <script>
        //根据css选择器 选择所有按钮
        const btns = document.querySelectorAll('button');
        let x = null; //设置为全局的 

        btns[0].onclick = function(){
            x = new XMLHttpRequest();
            x.open("GET",'http://127.0.0.1:8000/delay');
            x.send();
        }
        // abort
        btns[1].onclick = function(){
            x.abort();
        }
    </script>
</body>
</html>
重复请求:

​ 如果用户多次向服务端请求,到导致服务器压力很大,我们可以对多次请求只保留一次。如果点击多次,取出前面的请求,保留最后一次请求。

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>重复请求问题</title>
</head>
<body>
    <button>点击发送</button>
    <script>
        //获取元素对象
        const btns = document.querySelectorAll('button');
        let x = null;
        //标识变量
        let isSending = false; // 是否正在发送AJAX请求

        btns[0].onclick = function(){
            //判断标识变量
            if(isSending) x.abort();// 如果上一个正在发送 我们把上一个取消掉
            x = new XMLHttpRequest();
            //修改 标识变量的值
            isSending = true;
            x.open("GET",'http://127.0.0.1:8000/delay');
            x.send();
            // 回调函数
            x.onreadystatechange = function(){
                if(x.readyState === 4){
                    //修改标识变量
                    isSending = false;
                }
            }
        }

        // abort
        btns[1].onclick = function(){
            x.abort();
        }
    </script>
</body>
</html>
js 复制代码
app.all('/delay', (request, response) => {
    response.setHeader('Access-Control-Allow-Origin', '*');
    response.setHeader('Access-Control-Allow-Headers', '*');
    setTimeout(() => {
        response.send('延时响应');
    }, 3000)
});

JQuery

我向搭建一个网页,用于测试三种发送方式。

js 复制代码
//jQuery 服务
app.all('/jquery-server', (request, response) => {
    //设置响应头  设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    response.setHeader('Access-Control-Allow-Headers', '*');
    // response.send('Hello jQuery AJAX');
    const data = { name: '我是帅哥' };
    response.send(JSON.stringify(data));
});
get:

四个参数 : 请求的url ,发送参数对象,回调函数 ,响应体类型

js 复制代码
    $('button').eq(0).click(function(){
            $.get('http://127.0.0.1:8000/jquery-server', {a:100, b:200}, function(data){
                console.log(data);
            },'json');
        });
复制代码
data 就是响应体,xhr.response 
post:
js 复制代码
  $('button').eq(1).click(function () {
            $.post('http://127.0.0.1:8000/jquery-server', { a: 100, b: 200 }, function (data) {
                console.log(data);
                console.log(typeof data)
            });
        });

不加上面的第四个参数,返回的就是字符串。

通用写法:
js 复制代码
$('button').eq(2).click(function () {
            $.ajax({
                //url
                url: 'http://127.0.0.1:8000/jquery-server',
                //参数
                data: { a: 100, b: 200 },
                //请求类型
                type: 'GET',
                //响应体结果
                dataType: 'json',
                //成功的回调
                success: function (data) {
                    console.log(data);
                   console.log(typeof data);
                },
                //超时时间
                timeout: 2000,
                //失败的回调
                error: function () {
                    console.log('出错啦!!');
                },
                //头信息
                headers: {
                    c: 300,
                    d: 400
                }
            });
        });
html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>jQuery 发送 AJAX 请求</title>
    <link crossorigin="anonymous" href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css"
        rel="stylesheet">
    <script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>

<body>
    <div class="container">
        <h2 class="page-header">jQuery发送AJAX请求 </h2>
        <button class="btn btn-primary">GET</button>
        <button class="btn btn-danger">POST</button>
        <button class="btn btn-info">通用型方法ajax</button>
    </div>
    <script>
        $('button').eq(0).click(function () {
            $.get('http://127.0.0.1:8000/jquery-server', { a: 100, b: 200 }, function (data) {
                console.log(data);
            }, 'json');
        });

        $('button').eq(1).click(function () {
            $.post('http://127.0.0.1:8000/jquery-server', { a: 100, b: 200 }, function (data) {
                console.log(data);
                console.log(typeof data)
            });
        });

        $('button').eq(2).click(function () {
            $.ajax({
                //url
                url: 'http://127.0.0.1:8000/jquery-server',
                //参数
                data: { a: 100, b: 200 },
                //请求类型
                type: 'GET',
                //响应体结果
                dataType: 'json',
                //成功的回调
                success: function (data) {
                    console.log(data);
                    console.log(typeof data);
                },
                //超时时间
                timeout: 2000,
                //失败的回调
                error: function () {
                    console.log('出错啦!!');
                },
                //头信息
                headers: {
                    c: 300,
                    d: 400
                }
            });
        });

    </script>
</body>

</html>

axios

​ Axios 是一个基于 Promise 的 JavaScript HTTP 客户端,用于浏览器和 Node.js 环境中发送 HTTP 请求。它提供了一种简洁、直观的方式来执行异步请求,并处理请求和响应的数据。

GitHub地址:https://github.com/axios/axios

get
html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>axios 发送 AJAX请求</title>
    <script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/axios/0.19.2/axios.js"></script>
</head>
<body>
    <button>GET</button>
    <button>POST</button>
    <button>AJAX</button>
    <script>
        const btns = document.querySelectorAll('button');
        //配置 baseURL
        axios.defaults.baseURL = 'http://127.0.0.1:8000';
        btns[0].onclick = function () {
            //GET 请求
            axios.get('/axios-server', {
                //url 参数
                params: {
                    id: 100,
                    vip: 7
                },
                //请求头信息
                headers: {
                    name: 'demo',
                    age: 20
                }
            }).then(value => { // 基于promise
                console.log(value);
            });
        }

        
   
    </script>
</body>

</html>

后端服务器:

js 复制代码
//axios 服务
app.all('/axios-server', (request, response) => {
    //设置响应头  设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    // 运行自定义设置header
    response.setHeader('Access-Control-Allow-Headers', '*');
    // response.send('Hello jQuery AJAX');
    const data = { name: '我是帅哥' };
    response.send(JSON.stringify(data));
});

请求得到的响应数据:

post:
js 复制代码
btns[1].onclick = function () {
            axios.post('/axios-server', {
                username: 'admin',
                password: 'admin'
                // 表单数据  
            }, {
                //url 路径字符串
                params: {
                    id: 200,
                    vip: 9
                },
                //请求头参数
                headers: {
                    height: 180,
                    weight: 180,
                }
            });
        }
    
通用方法:
js 复制代码
     btns[2].onclick = function(){
            axios({
                //请求方法
                method : 'POST',
                //url
                url: '/axios-server',
                //url查询字符串 
                params: {
                    vip:10,
                    level:30
                },
                //请求头信息 
                headers: {
                    a:100,
                    b:200
                },
                //请求载荷数据
                data: {
                    username: 'admin',
                    password: 'admin'
                }
            }).then(response=>{
                //响应状态码
                console.log(response.status);
                //响应状态字符串
                console.log(response.statusText);
                //响应头信息
                console.log(response.headers);
                //响应体
                console.log(response.data);
            })
        }

fetch

简介:

fetch 是一个用于发送 HTTP 请求的现代 JavaScript API,内置于浏览器中,可以在前端代码中使用。它提供了一种基于 Promise 的方式来发送和处理网络请求。

post:
html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>fetch 发送 AJAX请求</title>
</head>
<body>
    <button>AJAX请求</button>
    <script>
        //文档地址
        //https://developer.mozilla.org/zh-CN/docs/Web/API/WindowOrWorkerGlobalScope/fetch
        
        const btn = document.querySelector('button');

        btn.onclick = function(){
            fetch('http://127.0.0.1:8000/fetch-server?vip=10', {
                //请求方法
                method: 'POST',
                //请求头
                headers: {
                    name:'atguigu'
                },
                //请求体
                body: 'username=admin&password=admin'
            }).then(response => {
                // return response.text();
                return response.json(); //json对象
            }).then(response=>{
                console.log(response);
            });
        }
    </script>
</body>
</html>
js 复制代码
//fetch 服务
app.all('/fetch-server', (request, response) => {
    //设置响应头  设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    response.setHeader('Access-Control-Allow-Headers', '*');
    const data = { name: '我是帅哥' };
    response.send(JSON.stringify(data));
});
相关推荐
玖釉-1 分钟前
解决PowerShell执行策略导致的npm脚本无法运行问题
前端·npm·node.js
Larcher35 分钟前
新手也能学会,100行代码玩AI LOGO
前端·llm·html
徐子颐1 小时前
从 Vibe Coding 到 Agent Coding:Cursor 2.0 开启下一代 AI 开发范式
前端
小月鸭1 小时前
如何理解HTML语义化
前端·html
jump6801 小时前
url输入到网页展示会发生什么?
前端
诸葛韩信1 小时前
我们需要了解的Web Workers
前端
brzhang2 小时前
我觉得可以试试 TOON —— 一个为 LLM 而生的极致压缩数据格式
前端·后端·架构
yivifu2 小时前
JavaScript Selection API详解
java·前端·javascript
这儿有一堆花2 小时前
告别 Class 组件:拥抱 React Hooks 带来的函数式新范式
前端·javascript·react.js
十二春秋2 小时前
场景模拟:基础路由配置
前端