AJAX、Axios

AJAX

AJAX 全称为Asynchronous JavaScript And XML,就是异步的JS 和XML
通过AJAX 可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据
AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式

1.2 XML 简介
XML 可扩展标记语言。
XML 被设计用来传输和存储数据。
XML 和HTML 类似,不同的是HTML 中都是预定义标签,而XML 中没有预定义标签,
全都是自定义标签,用来表示一些数据。

用XML 表示:

<student>
	<name>孙悟空</name>
	<age>18</age>
	<gender>男</gender>
</student>

现在已经被JSON 取代了。

{"name":"孙悟空","age":18,"gender":"男"}

AJAX 的优点

可以无需刷新页面而与服务器端进行通信
允许你根据用户事件来更新部分页面内容

AJAX 的缺点

没有浏览历史,不能回退
存在跨域问题(同源)
SEO 不友好

不同类型的请求及其作用

GET: 从服务器端读取数据(查)
POST: 向服务器端添加新数据 (增)
PUT: 更新服务器端已经数据 (改)
DELETE: 删除服务器端数据 (删)

常见的响应状态码

1XX Informational(信息性状态码) 接受的请求正在处理
2XX Success(成功状态码) 请求正常处理完毕
3XX Redirection(重定向状态码) 需要进行附加操作以完成请求
4XX Client Error(客户端错误状态码) 服务器无法处理请求
5XX Server Error(服务器错误状态码) 服务器处理请求出错

100 Continue 继续。客户端应继续其请求
101 Switching Protocols 切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议
200 OK 请求成功。一般用于GET与POST请求
201 Created 已创建。成功请求并创建了新的资源
202 Accepted 已接受。已经接受请求,但未处理完成
203 Non-Authoritative Information 非授权信息。请求成功。但返回的meta信息不在原始的服务器,而是一个副本
204 No Content 无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档
205 Reset Content 重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域
206 Partial Content 部分内容。服务器成功处理了部分GET请求
300 Multiple Choices 多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择
301 Moved Permanently 永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替
302 Found 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI
303 See Other 查看其它地址。与301类似。使用GET和POST请求查看
304 Not Modified 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源
305 Use Proxy 使用代理。所请求的资源必须通过代理访问
306 Unused 已经被废弃的HTTP状态码
307 Temporary Redirect 临时重定向。与302类似。使用GET请求重定向
400 Bad Request 客户端请求的语法错误,服务器无法理解
401 Unauthorized 请求要求用户的身份认证
402 Payment Required 保留,将来使用
403 Forbidden 服务器理解请求客户端的请求,但是拒绝执行此请求
404 Not Found 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面
405 Method Not Allowed 客户端请求中的方法被禁止
406 Not Acceptable 服务器无法根据客户端请求的内容特性完成请求
407 Proxy Authentication Required 请求要求代理的身份认证,与401类似,但请求者应当使用代理进行授权
408 Request Time-out 服务器等待客户端发送的请求时间过长,超时
409 Conflict 服务器完成客户端的 PUT 请求时可能返回此代码,服务器处理请求时发生了冲突
410 Gone 客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置
411 Length Required 服务器无法处理客户端发送的不带Content-Length的请求信息
412 Precondition Failed 客户端请求信息的先决条件错误
413 Request Entity Too Large 由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个Retry-After的响应信息
414 Request-URI Too Large 请求的URI过长(URI通常为网址),服务器无法处理
415 Unsupported Media Type 服务器无法处理请求附带的媒体格式
416 Requested range not satisfiable 客户端请求的范围无效
417 Expectation Failed 服务器无法满足Expect的请求头信息
500 Internal Server Error 服务器内部错误,无法完成请求
501 Not Implemented 服务器不支持请求的功能,无法完成请求
502 Bad Gateway 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应
503 Service Unavailable 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中
504 Gateway Time-out 充当网关或代理的服务器,未及时从远端服务器获取请求
505 HTTP Version not supported 服务器不支持请求的HTTP协议的版本,无法完成处理

get代码编写


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

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

// 3. 创建路由规则
app.get('/server', (request, response) => {
  // 设置响应头 设置允许跨域
  response.setHeader('Access-Control-Allow-Origin', '*');
  // 设置响应体
  response.send("Hello Ajax");
});

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

启动服务

node server.js
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <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')
      // 3. 发送
      xhr.send();
      // 4. 事件绑定 处理服务端返回的结果
      xhr.onreadystatechange = function(){
        // readyState 是 xhr 对象中的属性, 表示状态 0 1 2 3 4
        //判断 (服务端返回了所有的结果)
        if(xhr.readyState === 4){
          //判断响应状态码 200  404  403 401 500
          if(xhr.status >= 200 && xhr.status < 300){
            // 处理结果 行 头 空行 体
            // 响应
            console.log('状态码', xhr.status); // 状态码
            console.log('状态字符串', xhr.statusText); // 状态字符串
            console.log('所有响应头', xhr.getAllResponseHeaders()); // 所有响应头
            console.log('响应体', xhr.response); // 响应体
            
            //设置 result 的文本
            result.innerHTML=xhr.response;
          }else{
          }
        }
      } 
    }
  </script>
</body>
</html>

设置参数格式

xhr.open('GET', 'http://127.0.0.1:8000/server?a=100&b=200&c=300');

post代码编写

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Ajax POST 请求</title>
    <style>
        #result {
            width: 200px;
            height: 100px;
            border: solid 1px #903;
        }
    </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');
            // 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>
//1.引入express 
const express = require('express');
//2.创建应用对象
const app = express();



//3.创建路由规则
app.post('/server', (request, response) => {
//app.all('/server', (request, response) => {
    // 设置响应头,设置允许跨域
    response.setHeader("Access-Control-Allow-Origin", '*');
    response.send("Hello Ajax");

});

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

json

app.all('/json-server', (request, response) => {
  // 设置响应头, 设置允许跨域
  response.setHeader('Access-Control-Allow-Origin', '*');
  // 设置响应头, 设置允许自定义头信息
  response.setHeader('Access-Control-Allow-Headers', '*');
  // 响应一个数据
  const data = {
    name: 'wei'
  };
  // 对 对象 进行 字符串 转换
  let str = JSON.stringify(data)
  // 设置响应体 
  response.send(str);
});

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <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();
      // *2*.(自动转换) 设置响应体数据的类型(自动转换)
      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);
            // 1. 手动对数据转化 (字符串再转换成json)
            // let data = JSON.parse(xhr.response); //转换成json
            // result.innerHTML = data.name;
            // *2*. (自动转换)自动转换(自动转换)
            result.innerHTML = xhr.response.name; //已经自动变成json
          }
        }
      }
    }
  </script>
</body>
</html>

自动重启工具安装

npm install -g nodemon
nodemon demo01.js

IE缓存,用时间戳

问题:在一些浏览器中(IE),由于缓存机制的存在,ajax 只会发送的第一次请求,剩余多次请求不会在发送给浏览器而是直接加载缓存中的数据。
解决方式:浏览器的缓存是根据url 地址来记录的,所以我们只需要修改url 地址即可避免缓存问题

xhr.open("get","/testAJAX?t="+Date.now());

请求超时与网络异常

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</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];
        const result = document.querySelector('#result');
        btn.addEventListener('click', function() {
            const xhr = new XMLHttpRequest();
            // 超时设置
            xhr.timeout = 2000;
            xhr.ontimeout = function() {
                alert("网络超时");
            }
            xhr.ontimeout = 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) {
                        console.log(xhr.response);
                        // 1. 手动对数据转化 (字符串再转换成json)
                        // let data = JSON.parse(xhr.response); //转换成json
                        // result.innerHTML = data.name;
                        // *2*. (自动转换)自动转换(自动转换)
                        result.innerHTML = xhr.response; //已经自动变成json
                    }
                }
            }
        })
    </script>
</body>

</html>
//1.引入express 
const express = require('express');
const { setTimeout } = require('timers/promises');
//2.创建应用对象
const app = express();


//3.创建路由规则

app.all('/delay', (request, response) => {
    // 设置响应头,设置允许跨域
    response.setHeader("Access-Control-Allow-Origin", '*');
    setTimeout(() => {
        response.send('延时响应');
    }, 3000)

});

//

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

取消请求

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <button>点击发送</button>
    <button>点击取消</button>
    <script>
        let x = new XMLHttpRequest();
        const btns = document.querySelectorAll('button');
        btns[0].onclick = function() {

            x.open("GET", "http://127.0.0.1:8000/undo")
            x.send();
        }
        btns[1].onclick = function() {
            x.abort();
        }
    </script>
</body>

</html>
//1.引入express 
const express = require('express');
const { setTimeout } = require('timers/promises');
//2.创建应用对象
const app = express();


//3.创建路由规则

app.all('/undo', (request, response) => {
    // 设置响应头,设置允许跨域
    response.setHeader("Access-Control-Allow-Origin", '*');
    setTimeout(() => {
        response.send('延时响应');
    }, 3000)

});

//

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

取消重复请求

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <button>点击发送</button>
    <script>
        let isSentding = false;
        const btns = document.querySelectorAll('button');
        let x = new XMLHttpRequest();
        btns[0].onclick = function() {
            // 如果正在发送,取消新的请求;

            isSentding = true;
            if (isSentding) {
                x.abort();
            }
            x.open("GET", "http://127.0.0.1:8000/")
            x.send();
            x.onreadystatechange = function() {
                if (x.readyState === 4) {
                    isSentding = false;
                }
            }
        }
    </script>
</body>

</html>
//1.引入express 
const express = require('express');
const { setTimeout } = require('timers/promises');
//2.创建应用对象
const app = express();


//3.创建路由规则

app.all('/', (request, response) => {
    // 设置响应头,设置允许跨域
    response.setHeader("Access-Control-Allow-Origin", '*');
    setTimeout(() => {
        response.send('延时响应');
    }, 3000)


});

//

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

jQuery发送AJAX请求

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 不携带cookie -->
    <script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/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-info">POST</button>
        <button class="btn btn-primary">通用型方法ajax</button>
    </div>
    <script>
        $('button').eq(0).click(function() {
            $.get('http://127.0.0.1:8000/', {
                    a: 100,
                    b: 200
                },
                function(data) {
                    console.log(data);

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

                })
        })
        $('button').eq(2).click(function() {
            $.ajax({
                url: "http://127.0.0.1:8000/",
                data: {
                    a: 100,
                    b: 200
                },
                type: 'GET',
                dataType: 'json',
                success: function(data) {
                    console.log(data);
                },
                // 超时
                timeout: 2000,
                // 失败
                error: function() {
                    console.log("error");
                },
                headers: {
                    c: 300,
                    d: 400
                }
            })

        })
    </script>
</body>


</html>
//1.引入express 
const { json } = require('express');
const express = require('express');
const { setTimeout } = require('timers/promises');
//2.创建应用对象
const app = express();


//3.创建路由规则

app.all('/', (request, response) => {
    // 设置响应头,设置允许跨域
    response.setHeader("Access-Control-Allow-Origin", '*');
    // 设置自定义请求头
    response.setHeader("Access-Control-Allow-Headers", "*")
    const data = { name: 'dataset' }
    response.send(JSON.stringify(data));


});

//

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

axios

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.js"></script>
</head>

<body>
    <div class="container">
        <button>GET</button>
        <button>POST</button>
        <button>ajax</button>
    </div>
    <script>
        const btns = document.querySelectorAll('button');
        // 配置baseURL
        axios.defaults.baseURL = 'http://127.0.0.1:8000'
        btns[0].onclick = function() {
            axios.get('/axios-server', {
                params: {
                    id: 100,
                    vip: 7
                },
                headers: {
                    name: "headerdemo",
                    age: 20
                }
            }).then(value => {
                console.log(value);
            });
        }
        btns[1].onclick = function() {
            axios.post('/axios-server', {
                username: 'admin',
                password: 'admin'
            }, {
                params: {
                    id: 200,
                    vip: 9
                },
                headers: {
                    height: 100,
                    width: 100
                },
            })
        }
        btns[2].onclick = function() {
            axios({
                method: 'POST',
                url: '/axios-server',
                paramsL: {
                    vip: 10,
                    level: 30
                },
                headers: {
                    height: 200,
                    width: 200
                },
                data: {
                    username: 'admin',
                    password: 'admin'
                }

            }).then(response => {
                console.log(response);
            })
        }
    </script>
</body>

</html>
//1.引入express 
const { json } = require('express');
const express = require('express');
const { setTimeout } = require('timers/promises');
//2.创建应用对象
const app = express();


//3.创建路由规则

app.all('/axios-server', (request, response) => {
    // 设置响应头,设置允许跨域
    response.setHeader("Access-Control-Allow-Origin", '*');
    // 设置自定义请求头
    response.setHeader("Access-Control-Allow-Headers", "*")
    const data = { name: 'dataset' }
    response.send(JSON.stringify(data));


});

//

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

fetch

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <button>AJAX请求</button>
    <script>
        const btn = document.querySelector('button');
        btn.onclick = function() {
            fetch('http://127.0.0.1:8000/fetch-server', {
                //请求方法
                method: 'POST',
                headers: {
                    name: 'headername'

                },
                body: 'username=admin$password=admin'
            }).then(response => {
                return response.json();
            }).then(response => {
                console.log(response);
            });
        }
    </script>
</body>

</html>
//1.引入express 
const { json } = require('express');
const express = require('express');
const { setTimeout } = require('timers/promises');
//2.创建应用对象
const app = express();


//3.创建路由规则

app.all('/fetch-server', (request, response) => {
    // 设置响应头,设置允许跨域
    response.setHeader("Access-Control-Allow-Origin", '*');
    // 设置自定义请求头
    response.setHeader("Access-Control-Allow-Headers", "*")
    const data = { name: 'dataset' }
    response.send(JSON.stringify(data));


});

//

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

同源策略

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <h1>尚硅谷</h1>
    <button>点击获取用户数据</button>
    <script>
        const btn = document.querySelector('button');
        btn.onclick = function() {
            const x = new XMLHttpRequest();
            // 因为满足同源策略,url可以简写
            x.open("GET", '/data');
            x.send();
            x.onreadystatechange = function() {
                if (x.readyState == 4) {
                    if (x.status >= 200 && x.status <= 300) {
                        console.log(x.response);
                    }
                }
            }

        }
    </script>
</body>

</html>
//1.引入express 
const express = require('express');
//2.创建应用对象
const app = express();


//3.创建路由规则

app.get('/home', (request, response) => {
    // // 设置响应头,设置允许跨域
    // response.setHeader("Access-Control-Allow-Origin", '*');
    // // 设置自定义请求头
    // response.setHeader("Access-Control-Allow-Headers", "*")

    response.sendFile(__dirname + "/index.html");

});
app.get('/data', (request, response) => {

    response.send('用户数据')

});

//

//4.监听端口启动服务
app.listen(9000, () => {
    console.log("服务已经启动")
})
上一篇:简单理解XHR、Ajax、Axios、Promise


下一篇:面试小记(一)