無.Flac's Blog

無.Flac

AJAX 「 ※ Learning ※ 」

2025-03-12

简介

AJAX 全称为 Asynchronous JavaScript And XML,就是异步的 JS 和 XML。

通过 AJAX 可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据

AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。


【原生】AJAX请求

准备工作

1、前往 Node.js 官方网站 并下载适合你操作系统的 Node.js 安装程序。

2、前往并下载 Express 框架。

安装Node.js

node -v //检查Node.js版本
npm -v // 检查Npm包版本
npm install -g npm // 更细Npm

安装Express

npm init --yes
npm i express //mac用户前置sudo命令

HTTP协议请求

HTTP(hypertext transport protocol)协议『超文本传输协议』,协议详细规定了浏览器和万维网服务器之间互相通信的规则。

请求报文

格式

参数

请求行

POST /form.html HTTP/1.1

请求头

Host: www.example.com

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)

Content-Type: application/x-www-form-urlencoded

Content-Length: 27

空行

请求体

/username=admin&password=admin

响应报文

格式

参数

状态行

HTTP/1.1 200 OK

响应头

Date: Wed, 21 Oct 2015 10:55:34 GMT

Content-Type: text/html; charset=UTF-8

Content-Length: 1354

Content-encoding: gzip

空行

响应体

<html>
  <head> </head>
  <body>
    <h1>hello ,Ajax !</h1>
  </body>
</html>

状态码

状态码

类别

描述

100

信息性状态码

Continue:继续执行。

101

信息性状态码

Switching Protocols:切换协议。

200

成功状态码

OK:请求成功。

201

成功状态码

Created:请求成功并且服务器创建了新的资源。

202

成功状态码

Accepted:请求已接受,但处理尚未完成。

204

成功状态码

No Content:请求成功,但响应不包含内容。

301

重定向状态码

Moved Permanently:请求的资源已被永久移动到新位置。

302

重定向状态码

Found:请求的资源临时从不同的URI响应。

304

重定向状态码

Not Modified:资源未修改,可以使用客户端缓存的版本。

400

客户端错误状态码

Bad Request:请求无效或无法被服务器理解。

401

客户端错误状态码

Unauthorized:请求需要用户认证。

403

客户端错误状态码

Forbidden:服务器拒绝请求。

404

客户端错误状态码

Not Found:请求的资源在服务器上不存在。

500

服务器错误状态码

Internal Server Error:服务器遇到未知错误。

501

服务器错误状态码

Not Implemented:服务器不支持请求的功能。

502

服务器错误状态码

Bad Gateway:网关或代理服务器从上游服务器收到无效响应。

Express规则

// 引入express
const express = require('express');

// 创建应用对象
const app = express();

// 创建路由规则
// request是对请求报文的封装
// response是对响应报文的封装
app.get('/server',(request,response)=>{
    // 设置响应头,设置允许跨域
    response.setHeader('Access-Control-Allow-Origin','*')
    // 设置响应体
    response.send('Hello AJAX!')
})
app.post('/server', (request, response) => {
    // 设置响应头,设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*')
    // 设置响应体
    response.send('Hello AJAX!')
})
// 监听端口,启动服务
app.listen(8000, ()=>{
    console.log('服务器已启动,8000端口监听中...')
})

AJAX基本操作

<button>点我发送请求</button>
<div id="result" class="w-48 h-48 border solid black"></div>
<script>
    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');
        // 3. 发送
        xhr.send(); 

        // 4. 事件绑定 处理服务端返回的结果
        // on when 当....时候

        // readystate 是xhr对象中的属性,表示状态 0-4
        // 0:xhr对象创建完成
        // 1:open方法调用完成
        // 2:send方法调用完成
        // 3:服务端返回部分结果
        // 4:服务端返回所有结果,可以在该阶段获取返回结果

        // change 改变
        xhr.onreadystatechange = function() {
            // 判断服务端返回所有结果
            if (xhr.readyState === 4) {
                // 判断响应状态码 200 404 403 401 500
                // 2xx 都为成功
                if (xhr.status >= 200 && xhr.status < 300) {
                    // 处理结果 行 头 空行 体
                    // 1. 响应行
                    // console.log(xhr.status); // 状态码
                    // console.log(xhr.statusText); // 状态字符串
                    // console.log(xhr.getAllResponseHeaders()); // 所有响应头
                    // console.log(xhr.response); // 响应体
                    // 设置result的文本
                    result.innerText = xhr.response;
                }
            }
        }
    }
</script>

POST请求设置

/* 当鼠标移入#result,则发送Post请求... */
<div id="result" class="w-48 h-48 border solid black"></div>
<script>
    const result = document.getElementById('result');
    result.addEventListener('mouseover', function () {
        //1.创建对象
        const xhr = new XMLHttpRequest();
        //2.初始化
        xhr.open('POST', 'http://127.0.0.1:8000/server');
        xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); // 设置请求头信息(预定义)
        xhr.setRequestHeader('name','parlo'); //可以设置自定义请求头
        //3.发送
        xhr.send('a=100&b=200'); //请求体也可以为'number';'a:100&b:100..'
        //4.事件绑定
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                if (xhr.status >= 200 && xhr.status < 300) {
                    result.innerText = xhr.response;
                }
            }
        }
    });
</script>

当设定为自定义的请求头时,则需要在后端添加新的请求类型(一般不需要前端去操作)

// server.js

// 可以接受任意类型的请求
app.all('/server', (request, response) => {
    // 设置响应头,设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*')
    response.setHeader('Access-Control-Allow-Headers', '*')
    // 设置响应体
    response.send('Hello AJAX!')
})

服务端响应JSON数据

// server.js

// 可以接受任意类型的请求
app.all('/json-server', (request, response) => {
    // 设置响应头,设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*')
    response.setHeader('Access-Control-Allow-Headers', '*')
    // 响应一个数据
    const data = {
        name: 'parlo',
    }
    // 对象转换为字符串
    let str = JSON.stringify(data)
    // 设置响应体
    response.send(str)
})
/* 当键盘在浏览器视口按下,则发送请求 */
<div id="result" class="w-48 h-48 border solid black"></div>

手动转换数据

<script>
    //当键盘在浏览器视口下,按下键盘则发送POST请求
    const result = document.getElementById('result')
    window.onkeydown = function () {
        // 发送请求
        const xhr = new XMLHttpRequest();
        // 初始化
        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) {
                    // 手动处理服务器返回的结果
                    let data = JSON.parse(xhr.response)
                    console.log(data)
                    result.innerText = data.name
                }
            }
        }
    }
</script>

自动转换数据

<script>
    //当键盘在浏览器视口下,按下键盘则发送POST请求
    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) {
                    // 自动处理服务器返回的结果
                    console.log(xhr.response)
                    result.innerText = xhr.response.name
                }
            }
        }
    }
</script>

Nodemon工具

安装Nodemon

npm install -g nodemon

运行服务端

nodemon server.js

IE缓存问题解决

解决全世界最好用的IE浏览器的缓存解决问题!需要注意的是,现代浏览器几乎不需要调整。

<button>点我发送请求</button>
<div id="result" class="w-48 h-48 border solid black"></div>
// server.js

app.get('/ie', (request, response) => {
    // 设置响应头,设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    // 设置响应体
    response.send('HELLO IE! 2~~~');
});
<script>
    const btn = document.getElementsByTagName('button')[0];
    const result = document.getElementById('result');
    btn.addEventListener('click', () => {
        const xhr = new XMLHttpRequest();
        // 初始化
        xhr.open('GET', 'http://localhost:8000/ie?t=' + Date.now()); //为IE浏览器添加参数 + 时间戳
        // 发送
        xhr.send();
        // 绑定事件
        xhr.onreadystatechange = () => {
            if (xhr.readyState === 4) {
                if (xhr.status >= 200 && xhr.status < 300) {
                    result.innerText = xhr.response;
                }
            }
        };
    });
</script>

超时与网络异常

增加友好的判定来告知AJAX请求的网络情况。

<button>点我发送请求</button>
<div id="result" class="w-48 h-48 border solid black"></div>
// server.js

app.get('/delay', (request, response) => {
    // 设置响应头,设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    // 设置响应体
    setTimeout(() => {
        response.send('延时响应');
    }, 3000);
});
<script>
    const btn = document.getElementsByTagName('button')[0];
    const result = document.getElementById('result');
    btn.addEventListener('click', () => {
        // 创建对象
        const xhr = new XMLHttpRequest();
        // 设置超时时间
        xhr.timeout = 2000;
        // 设置超时回调
        xhr.ontimeout = function () {
            alert('网络超时,请稍后重试!');
        };
        // 设置网络异常回调
        xhr.onerror = function () {
            alert('网络异常,请稍后重试!');
        };
        // 初始化
        xhr.open('GET', 'http://localhost:8000/delay');
        // 发送
        xhr.send();
        // 事件绑定
        xhr.onreadystatechange = () => {
            if (xhr.readyState === 4) {
                if (xhr.status >= 200 && xhr.status < 300) {
                    result.innerText = xhr.response;
                }
            }
        };
    });
</script>

取消请求

取消正在发送的AJAX请求。

<button>点击发送请求</button>
<button>点击取消请求</button>
<script>
    const btn = document.querySelectorAll('button');

    let xhr = null; // 作用域需放在外层

    btn[0].onclick = function () {
        xhr = new XMLHttpRequest();
        xhr.open('GET', 'http://localhost:8000/delay');
        xhr.send();
    };
    btn[1].onclick = function () {
        xhr.abort(); //取消请求
    };
</script>

重复请求问题

当多次发送AJAX请求时,取消之前的请求。这样可以减少服务器的性能冲突。

<script>
    const btn = document.querySelectorAll('button');
    let xhr = null;
    //标识变量
    let isSending = false; // 是否正在发送AJAX请求
    btn[0].onclick = function () {
        if (isSending) xhr.abort();//判断!如果正在发送,则取消本次发送
        xhr = new XMLHttpRequest();
        //修改 标识变量的值
        isSending = true;
        xhr.open('GET', 'http://localhost:8000/delay');
        xhr.send();
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                //修改表示变量
                isSending = false;
            }
        };
    };
    btn[1].onclick = function () {
        xhr.abort(); // 取消请求
    };
</script>

【jQuery】AJAX请求

<button>GET请求</button>
<button>POST请求</button>
// jquery
app.all('/jquery-server', (request, response) => {
    // 设置响应头,设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*');
    // 设置响应体
    //response.send('HELLO jquery AJAX');
    const data = {name:'parlo'};
    response.send(JSON.stringify(data));
});

GET请求

<script>
    $('button').eq(0).click(function () {
        $.get('http://127.0.0.1:8000/jquery-server', {name: 'parlor', age: 18}, function (data) {
            console.log(data);
        }, 'json');
    });
</script>

POST请求

<script>
    $('button').eq(1).click(function () {
        $.post('http://127.0.0.1:8000/jquery-server', {name: 'parlor', age: 18}, function (data) {
            console.log(data);
        }, 'json');
    });
</script>

通用方法