Ajax和axios

一、原生Ajax

AJAX: 全称为Asynchronous Javascript And XML,就是异步的 JS 和 XML

  • 它可以使用 JSON,XML,HTML 和 text 文本等格式发送和接收数据
  • AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式
    所用依赖
"dependencies": {
    "@koa/router": "^12.0.0",
    "axios": "^0.27.2",
    "body-parser": "^1.19.0",
    "cookie-parser": "^1.4.5",
    "express": "^4.17.1",
    "express-session": "^1.17.2",
    "koa": "^2.13.4",
    "koa-body": "^5.0.0",
    "koa-logger": "^3.2.1",
    "koa-static": "^5.0.0",
    "koa2-cors": "^2.0.6",
    "mongodb": "^4.4.0",
    "nprogress": "^0.2.0",
    "qs": "^6.11.0"
  }

1.原生Ajax经典步骤

  • Ajax发送请求的经典步骤

    • 第一步:创建网络请求的AJAX对象(使用XMLHttpRequest)
    • 第二步:监听XMLHttpRequest对象状态的变化,或者监听onload事件(请求完成时触发)
    • 第三步:配置网络请求(通过open方法)
    • 第四步:发送send网络请求
  • XMLHttpRequest的state(状态)
    在一次网络请求中看到状态发生了很多次变化,这是因为对于一次请求来说包括如下的状态

    • 0 UNSENT 代理被创建,但尚未调用 open() 方法。
    • 1 OPENED open() 方法已经被调用。
    • 2 HEADERS_RECEIVED send() 方法已经被调用,并且头部和状态已经可获得。
    • 3 LOADING 下载中, responseText 属性已经包含部分数据。
    • 4 DONE 下载操作已完成。
  • 注意

    • 这个状态并非是HTTP的相应状态,而是记录的XMLHttpRequest对象的状态变化
    • http响应状态通过status获取

前端代码

<!-- 
    前端能发请求的方式:
        // =================  get 
            浏览器的地址栏
            a标签的href
            img标签src
            script标签的src
            link标签的href
            postman工具也可以发请求
            表单
            ajax
        // =================  post
            postman工具也可以发请求
            表单
            ajax

    AJAX:Asynchronous Javascript And XML(异步JavaScript和XML)
        并不是一个新技术,是多门技术的结合体,如:js bom json...

        作用:向后端发出请求,后端给出响应

    XML:
        HTML:
            <div>  <p>   <span> ... 
        XML:
            <pig>   <dog>   <student>...
            在10年前,是前后端通信的一种数据格式
            现在,前后端通信主要是以json为主
    
    -----------------------------------
    ajax发请求的经典步骤:
        1)创建一个ajax对象   XMLHttpRequest
        2)监听ajax对象的状态变化    或     监听onload事件
        3)配置网络请求
        4)发出请求
-->

<script>
    // 1)创建一个ajax对象   XMLHttpRequest   属于BOM中的内容
    let xhr = new XMLHttpRequest();
    console.log(xhr);
    console.log(xhr.readyState); // ajax刚创建出来的时状态是0

    // 2)监听ajax对象的状态变化 
    xhr.onreadystatechange = function() {
        // console.log("==>", xhr.readyState);
        // if(xhr.readyState === 4){
        //     console.log("-------------");
        //     console.log(xhr.response);
        //     console.log("-------------");
        // }

        if (xhr.readyState === XMLHttpRequest.DONE) {
            console.log("-------------");
            console.log(xhr.response);
            console.log("-------------");
        }
    }

    // 3)配置网络请求
    xhr.open("get", "http://127.0.0.1:3000/get")
    console.log(xhr.readyState); // 调用完open方法后,ajax的状态就变成1

    // 4)发出请求  send(请求体)  请求体就是给后端传递数据
    // get请求没有所谓的请求体  只有post请求才能请求体
    // 你发出了get请求,send()  ()中不需要写任何内容 
    xhr.send()
    console.log(xhr.readyState); // ajax的状态就变成1
</script>

后端代码

const Koa = require("koa");
const cors = require("koa2-cors");
const logger = require("koa-logger");
const Router = require("@koa/router");
const koaBody = require("koa-body");
const app = new Koa();
const router = new Router();

app.use(cors());
app.use(logger());
app.use(koaBody());

router.get("/get", async (ctx, next) => {
    ctx.status = 200;
    ctx.body = "hello Ajax";
});

app.use(router.routes())
router.allowedMethods();

app.listen(3000, () => {
    console.log("running in http://127.0.0.1:3000");
});

2.xhr对象的load事件

除了onreadystatechange还有其他的事件可以监听

  • loadstart:请求开始
  • progress: 一个响应数据包到达,此时整个 response body 都在 response 中
  • abort:调用 xhr.abort() 取消了请求
  • error:发生连接错误,例如,域错误。不会发生诸如 404 这类的 HTTP 错误
  • load:请求成功完成,我们也可以使用load来获取数据
  • timeout:由于请求超时而取消了该请求(仅发生在设置了 timeout 的情况下)
  • loadend:在 load,error,timeout 或 abort 之后触发
<script>
    let xhr = new XMLHttpRequest();

    // xhr.onreadystatechange = function () {
    //     if (xhr.readyState === 4) {
    //         console.log(xhr.response);
    //     }
    // }

    xhr.onload = function() {
        console.log(xhr.response);
    }

    xhr.open("get", "http://127.0.0.1:3000/get");
    xhr.send();
</script>

后端代码同上

3.响应JSON数据, 指定响应类型

XMLHttpRequest response 属性返回响应的正文内容

  • 返回的类型取决于responseType的属性设置
  • 通过responseType可以设置获取数据的类型
  • 早期通常服务器返回的数据是普通的文本和XML,所以我们通常会通过responseText、 responseXML来获取响应结果
  • 目前服务器基本返回的都是json数据,直接设置为json即可

前端代码

<script>
    let xhr = new XMLHttpRequest();

    xhr.onload = function() {
        console.log(xhr.response);
        console.log(xhr.response.name);
        console.log(xhr.response.culture);
        console.log(typeof xhr.response);
    }
    // 期望后端返回json数据,如果不作这样的配置,得到的是纯文本字符串
    xhr.responseType = "json";

    xhr.open("get", "http://127.0.0.1:3000/json");
    xhr.send();
</script>

后端代码

const Koa = require("koa");
const cors = require("koa2-cors");
const logger = require("koa-logger");
const Router = require("@koa/router");
const koaBody = require("koa-body");
const app = new Koa();
const router = new Router();

app.use(cors());
app.use(logger());
app.use(koaBody());

router.get("/json", async (ctx, next) => {
    ctx.status = 200;
    ctx.type = "json";
    ctx.body = {
        name: "码路教育",
        culture: "为学员服务",
    };
});

app.use(router.routes())
router.allowedMethods();

app.listen(3000, () => {
    console.log("running in http://127.0.0.1:3000");
});

4.响应XML数据

前端代码

<script>
    let xhr = new XMLHttpRequest();

    xhr.onload = function() {
        // console.log(xhr.response); 

        // 得到xml数据
        console.log(xhr.responseXML);
    }

    // xhr.responseType = "xml"  // 不OK

    xhr.open("get", "http://127.0.0.1:3000/xml");
    xhr.send();
</script>

后端代码

const Koa = require("koa");
const cors = require("koa2-cors");
const logger = require("koa-logger");
const Router = require("@koa/router");
const koaBody = require("koa-body");
const app = new Koa();
const router = new Router();

app.use(cors());
app.use(logger());
app.use(koaBody());

router.get("/xml", async (ctx, next) => {
    ctx.status = 200;
    ctx.type = "xml"
    ctx.body = `
        <content>
            <name>码路教育</name>
            <culture>为学员服务</culture>
        </content>
    `;
});

app.use(router.routes())
router.allowedMethods();

app.listen(3000, () => {
    console.log("running in http://127.0.0.1:3000");
});

5.响应的状态status

  • XMLHttpRequest的state是用于记录xhr对象本身的状态变化,并非针对于HTTP的网络请求状态
  • 如果我们希望获取HTTP响应的网络状态,可以通过status和statusText来获取

请添加图片描述
前端代码

<script>
    let xhr = new XMLHttpRequest();

    xhr.onload = function() {
        // console.log(xhr.response);

        // xhr.status,得到响应的状态码
        console.log(xhr.status);
    }

    // xhr.open("post", "http://127.0.0.1:3000/status/500");
    // xhr.open("post", "http://127.0.0.1:3000/status/503");
    xhr.open("post", "http://127.0.0.1:3000/status/404");
    xhr.send();
</script>

后端代码

const Koa = require("koa");
const cors = require("koa2-cors");
const logger = require("koa-logger");
const Router = require("@koa/router");
const koaBody = require("koa-body");
const app = new Koa();
const router = new Router();

app.use(cors());
app.use(logger());
app.use(koaBody());

router.post("/status/500", async (ctx, next) => {
    ctx.status = 500;
    ctx.body = 500;
});

router.post("/status/503", async (ctx, next) => {
    ctx.status = 503;
    ctx.body = 503;
});

router.post("/status/403", async (ctx, next) => {
    ctx.status = 403;
    ctx.body = 403;
});

router.post("/status/404", async (ctx, next) => {
    ctx.status = 404;
    ctx.body = {
        ok: 1
    };
});

app.use(router.routes())
router.allowedMethods();

app.listen(3000, () => {
    console.log("running in http://127.0.0.1:3000");
});

6.GET请求传递参数

常见的传递给服务器数据的方式有如下几种

  • 方式一:GET请求的query参数
  • 方式二:POST请求 x-www-form-urlencoded 格式
  • 方式三:POST请求 FormData 格式
  • 方式四:POST请求 JSON 格式

前端代码

<script>
    let xhr = new XMLHttpRequest();

    xhr.onload = function() {
        console.log(xhr.response);
    }

    xhr.responseType = "json"

    // query传参  在谷歌浏览器的控制台有一个payload  表示query传递的参数
    //  querystring  查询字符串
    // xhr.open("get", "http://127.0.0.1:3000/get?name=wc&age=18&address=bj");
    // xhr.send();

    // params传参
    // 在谷歌浏览器的控制台中没有payload  但是也给后端传递了参数
    xhr.open("get", "http://127.0.0.1:3000/get/wc/18/bj");
    xhr.send();
</script>

后端代码

const Koa = require("koa");
const cors = require("koa2-cors");
const logger = require("koa-logger");
const Router = require("@koa/router");
const koaBody = require("koa-body");
const app = new Koa();
const router = new Router();

app.use(cors());
app.use(logger());
app.use(koaBody());

router.get("/get", async (ctx, next) => {
    ctx.status = 200;
    ctx.body = ctx.query;
});

router.get("/get/:name/:age/:address", ctx => {
    ctx.status = 200;
    ctx.body = ctx.params;
})

app.use(router.routes())
router.allowedMethods();

app.listen(3000, () => {
    console.log("running in http://127.0.0.1:3000");
});

7. post请求传递参数

前端代码

<script>
    let xhr = new XMLHttpRequest();

    xhr.onload = function() {
        console.log(xhr.response);
    }

    // xhr.responseType = "json"

    xhr.open("post", "http://127.0.0.1:3000/post");

    // 如果不设置请求求,默认Content-Type是text/plain
    // 此时谷歌浏览器调度面板中的payload显示Request Data
    // Content-Type: text / plain; charset = UTF - 8

    // 如果配置了请求头是application/x-www-form-urlencoded
    // 此时谷歌浏览器调度面板中的payload显示Form Data
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")

    // post传参,需要放在请求体中
    // ()中请求体
    xhr.send("name=xq&age=28&address=zz");
</script>

后端代码

const Koa = require("koa");
const cors = require("koa2-cors");
const logger = require("koa-logger");
const Router = require("@koa/router");
const koaBody = require("koa-body");
const app = new Koa();
const router = new Router();

app.use(cors());
app.use(logger());
app.use(koaBody());

router.post("/post", async (ctx, next) => {
    ctx.status = 200;
    ctx.body = ctx.request.body;
});

app.use(router.routes())
router.allowedMethods();

app.listen(3000, () => {
    console.log("running in http://127.0.0.1:3000");
});

8. formData传递参数

FormData.append()

https://developer.mozilla.org/zh-CN/docs/Web/API/FormData/append

  • FormData 接口的append() 方法 会添加一个新值到 FormData 对象内的一个已存在的键中,如果键不存在则会添加该键。
  • FormData.set 和 append() 的区别在于,如果指定的键已经存在, FormData.set 会使用新值覆盖已有的值,而 append() 会把新值添加到已有值集合的后面。
    前端代码
formData.append(name, value);
formData.append(name, value, filename);

<meta charset="utf-8">
<form class="info">
    <input type="text" name="username">
    <input type="text" name="pwd">
</form>
<button class="send">发送请求</button>

<script>
    let formEle = document.querySelector(".info")
    let sendEle = document.querySelector(".send")
    sendEle.onclick = function() {
        let xhr = new XMLHttpRequest();
        xhr.onload = function() {
            console.log(xhr.response);
        }
        xhr.open("post", "http://127.0.0.1:3000/post");

        // formData传参,在谷歌浏览器的控制台中payload中显示form Data
        // 但是不一样的是 当点view source
        // formData是一个容器
        // let formData = new FormData();
        // formData.append("name", "z3")
        // formData.append("age", "18")
        // xhr.send(formData)

        let formData = new FormData(formEle);
        xhr.send(formData)
    }
</script>

后端代码

const Koa = require("koa");
const cors = require("koa2-cors");
const logger = require("koa-logger");
const Router = require("@koa/router");
// 之前: body-parser
// 现在: koa-body
const koaBody = require("koa-body");
const app = new Koa();
const router = new Router();

app.use(cors());
app.use(logger());
app.use(koaBody({
    multipart: true
}));

router.post("/post", async (ctx, next) => {
    ctx.status = 200;
    ctx.body = ctx.request.body;
});

app.use(router.routes())
router.allowedMethods();

app.listen(3000, () => {
    console.log("running in http://127.0.0.1:3000");
});

9. 传递多种形式的参数

前端代码

<script>
    let xhr = new XMLHttpRequest();
    xhr.onload = function() {
        console.log(xhr.response);
    }
    xhr.responseType = "json"

    xhr.open("post", "http://127.0.0.1:3000/post/wc/18?score=100&id=001");
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
    xhr.send("name=xq&age=28&address=zz");
</script>

后端代码

const Koa = require("koa");
const cors = require("koa2-cors");
const logger = require("koa-logger");
const Router = require("@koa/router");
// 之前: body-parser
// 现在: koa-body
const koaBody = require("koa-body");
const app = new Koa();
const router = new Router();

app.use(cors());
app.use(logger());
app.use(koaBody({
    multipart: true
}));

router.post("/post/:name/:age", async (ctx, next) => {
    ctx.status = 200;
    let postData = ctx.request.body;
    let paramsData = ctx.params;
    let queryData = ctx.query;
    console.log("postData:", postData);
    console.log("paramsData:", paramsData);
    console.log("queryData:", queryData);
    ctx.body = ctx.request.body;
});

app.use(router.routes())
router.allowedMethods();

app.listen(3000, () => {
    console.log("running in http://127.0.0.1:3000");
});

10.总结


    get传参:
        query传参
            /get?name=wc&amp;age18
            后端: ctx.query
            在谷歌浏览器控制台中有一个payload面板
            payload面板中显示 Query Stirng  查询字符串
        params传参
            /get/wc/18/bj
            后端: /get/:name/:age/:address
                 ctx.params
            在谷歌浏览器控制台中没有payload面板

    post传参:
        send中直接传递请求体:
            xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
            send(name=wc&amp;age=18&amp;address=bj)
            后端: 配置body-parser 或  koa-body 
            后端: ctx.request.body
            在谷歌浏览器控制台中有一个payload面板
            payload面板中显示 Form Data  点开view source 
                name=wc&amp;age=18&amp;address=bj

            如果没有配置
                xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
                谷歌浏览器控制台中有一个payload面板
                payload面板中显示 Request Data  

        把数据放到FormData容器:
            let formData = new FormData();
            向容器中放数据:
                1)formData.append("username","wc")
                2)在new FormData()直接指定表单  这样表单中的数据就是收集到容器

            谷歌浏览器控制台中有一个payload面板,payload面板中显示 Form Data,点开view source 和 send中传递请求体是不一样的

    如果是post传参,能不能传递query参数和params参数?
    答:可以

11. 检测用户名是否存在

前端代码

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

<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>

<body>
    <h2>用户注册</h2>
    <form method="post">
        <ul>
            <li>用户名:<input type="text" name="username" id="user"><span id="msg"></span></li>
            <li>密码:<input type="text" name="pwd"></li>
            <li>确认密码:<input type="text" name="repwd"></li>
            <li><input type="submit" value="注册"></li>
        </ul>
    </form>
    <script>
        let user = document.querySelector("#user")
        let msg = document.querySelector("#msg")

        user.onblur = function () {
            // this 表示事件源  this.value 表示输入框中的内容
            let username = this.value;

            let xhr = new XMLHttpRequest();
            xhr.onload = function () {
                let res = xhr.response;
                if (res.code == 0) {
                    msg.innerHTML = res.msg;
                    msg.style.color = "red"
                } else {
                    msg.innerHTML = res.msg;
                    msg.style.color = "green"
                }
            }
            xhr.responseType = "json"
            xhr.open("post", "http://127.0.0.1:3000/check");

            xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
            xhr.send(`username=${username}`)
        }
    </script>
</body>

</html>

后端代码

const Koa = require("koa");
const cors = require("koa2-cors");
const logger = require("koa-logger");
const Router = require("@koa/router");
const koaBody = require("koa-body");
const app = new Koa();
const router = new Router();

app.use(cors());
app.use(logger());
app.use(koaBody());

// 模拟从数据库中取到的用户信息
let users = ["wc", "xq", "admin"];

router.post("/check", (ctx) => {
    let username = ctx.request.body.username.trim();
    if (users.find(user => user === username)) {
        ctx.body = {
            code: 0,
            msg: "对不起,该用户名已经被注册,请换个用户名"
        }
    } else {
        ctx.body = {
            code: 1,
            msg: "恭喜你,该用户可以使用"
        }
    }

})

app.use(router.routes())
router.allowedMethods();

app.listen(3000, () => {
    console.log("running in http://127.0.0.1:3000");
});

12. 省市区三级联动

前端代码

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

<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>

<body>
    <h2>省市区三级联动</h2>
    <label for="">请选择省份:</label>
    <select id="province">
        <option value="">--省份--</option>
    </select>
    <select id="city">
        <option value="">--市区--</option>
    </select>
    <select id="country">
        <option value="">--区县--</option>
    </select>
    <script>
        let province = document.getElementById("province")
        let city = document.getElementById("city")

        // 请求所有的省份
        let xhr = new XMLHttpRequest(); // 第一步:创建xhr对象
        xhr.open("get", "http://127.0.0.1:3000/province"); // 第二步:建立连接
        xhr.send(null); // 第三步:发出请求  null可写可不写

        xhr.responseType = "json";

        // 一上来,就是获取所有的省
        xhr.onload = function() {
            let provinceData = xhr.response;

            let str = `<option value="">--省份--</option>`;
            provinceData.forEach(item => {
                str += `<option value="${item}">${item}</option>`
            })
            province.innerHTML = str;
        }

        province.onchange = function() {
            xhr.open("get", "http://127.0.0.1:3000/city?province=" + this.value)
            xhr.send(null);
            xhr.onload = function() {
                let cityData = xhr.response;
                let str = ` <option value="">--市区--</option>`;
                cityData.forEach(item => {
                    str += `<option value="${item}">${item}</option>`
                })
                city.innerHTML = str;
            }
                        city.onchange = function () {
                console.log(this.value);

                xhr.open("get", "http://127.0.0.1:3000/country?province=" + province + "&city=" + this.value);
                xhr.send(null)

                xhr.onload = function () {
                    let countryData = xhr.response;
                    let str = `<option value="">--区县--</option>`;
                    countryData.forEach(item => {
                        str += `<option value="${item}">${item}</option>`
                    })
                    country.innerHTML = str;
                }
            }
        }
    </script>
</body>

</html>

后端代码

const Koa = require("koa");
const cors = require("koa2-cors");
const logger = require("koa-logger");
const Router = require("@koa/router");
const koaBody = require("koa-body");
const app = new Koa();
const router = new Router();

app.use(cors());
app.use(logger());
app.use(koaBody());

// data表示服务器端的所有的数据
let data = require("./cityData.min.json")

// 响应所有的省份
router.get("/province", (ctx) => {
    let province = [];
    data.forEach(item => {
        // item代表每一个省的所有数据
        province.push(item.n)
    })
    // json有两种形式:1)对象的形式 2)数组的形式
    ctx.body = province; // 响应给xhr一个json字符串  ["北京市","河南省","河北省"...]
})

// 根据省份,响应对应的市
router.get("/city", (ctx) => {
    let province = ctx.query.province;
    let cities = [];
    data.forEach(item => {
        if (item.n === province) {
            item.s.forEach(item1 => {
                cities.push(item1.n)
            })
        }
    })
    ctx.body = cities
})
// 根据省份,响应对应的市,对应区
router.get("/country", (ctx) => {
    let province = ctx.query.province;
    let city = ctx.query.city;
    let countrys = []
    let arr = data.filter(item => {
        return item.n === province
    })[0].s

    arr.forEach(item => {
        if (item.n === city) {
            item.s && item.s.forEach(item1 => {
                countrys.push(item1.n)
            })
        }
    })
    ctx.body = countrys
})
app.use(router.routes())
router.allowedMethods();

app.listen(3000, () => {
    console.log("running in http://127.0.0.1:3000");
});

14. 传统ajax分页

前端代码

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

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        li {
            list-style: none;
        }

        body {
            background: #eee;
        }

        .wrapper {
            background: #fff;
            width: 970px;
            margin: 20px auto;
            padding: 15px;
        }

        h1 {
            text-align: center;
            border-bottom: 1px solid #ddd;
            padding-bottom: 20px;
        }

        li {
            margin: 20px 0;
            border-bottom: 1px dotted #eee;
            padding-bottom: 20px;
        }

        p {
            line-height: 25px;
        }
    </style>

    <!-- CDN -->
    <script src="https://libs.baidu.com/jquery/1.11.3/jquery.min.js"></script>
</head>

<body>
    <div class="wrapper">
        <h1>新闻列表(AJAX普通分页)
            <script>
                document.write(new Date().toLocaleString())
            </script>
        </h1>
        <ul>

        </ul>
        <div class="footer">
            <p>总共有<span id="total"></span>条新闻,每页显示<span id="pagesize"></span>条,
                当前是<span id="page"></span>/<span id="size"></span><a href="#" id="prev">上一页</a>
                <a href="#" id="next">下一页</a>
            </p>
        </div>
    </div>
    <script>
        let page = 1;
        let pageSize = 3;
        // axios  promise
        function getNewsList(page, pageSize) {

            $.get("http://127.0.0.1:3000/news", {
                page,
                pageSize
            }, res => {
                let str = "";
                res.news.forEach(item => {
                    str += `
                        <li>
                            <h2>${item.title}</h2>
                            <p class="time">${item.time}</p>
                            <p class="summary">${item.summary}</p>
                        </li>
                    `
                })
                $("ul").html(str)
                $("#total").html(res.total)
                $("#pagesize").html(res.pageSize)
                $("#page").html(res.page)
                $("#size").html(res.size)
            })

        }
        getNewsList(page, pageSize)

        $("#prev").click(function(e) {
            e.preventDefault();
            if (page > 1) {
                getNewsList(--page, pageSize)
            }
        })
        $("#next").click(function(e) {
            e.preventDefault();
            if (page < $("#size").html()) {
                getNewsList(++page, pageSize)
            }
        })
    </script>
</body>

</html>

后端代码

const Koa = require("koa");
const cors = require("koa2-cors");
const logger = require("koa-logger");
const Router = require("@koa/router");
const koaBody = require("koa-body");
const MongoClient = require('mongodb').MongoClient
const app = new Koa();
const router = new Router();

app.use(cors());
app.use(logger());
// app.use(koaBody());

const client = new MongoClient('mongodb://127.0.0.1:27017')
// 链接服务端
client.connect()
console.log('链接成功')

// 获取数据库 
const db = client.db('newsDB')
// 获取集合
const grade1 = db.collection('news')

router.get("/news", async ctx => {

    let page = ctx.query.page || 1;
    (page <= 0) && (page = 1)

    let pageSize = ctx.query.pageSize;
    let r = await grade1
        .find()
        .skip((page - 1) * pageSize)
        .limit(+pageSize)
        .toArray()

    let total = await grade1.find().count();
    let size = Math.ceil(total / pageSize) // size表示一共有多少页

    ctx.body = {
        news: r,
        total: total,
        pageSize,
        page,
        size
    }
    // 关闭客户端的链接
    // client.close()
})

app.use(router.routes())
router.allowedMethods();

app.listen(3000, () => {
    console.log("running in http://127.0.0.1:3000");
});
[
  {
    "title": "news标题001",
    "time": "2022-08-12",
    "summary": "刚刚收官的《大考》《底线》和《胡同》后,《追光者》《我们这十年》正在播出。《麓山之歌》《大山的女儿》又开始重播。"
  },
  {
    "title": "news标题002",
    "time": "2022-08-12",
    "summary": "刚刚收官的《大考》《底线》和《胡同》后,《追光者》《我们这十年》正在播出。《麓山之歌》《大山的女儿》又开始重播。"
  },
  {
    "title": "news标题003",
    "time": "2022-08-12",
    "summary": "刚刚收官的《大考》《底线》和《胡同》后,《追光者》《我们这十年》正在播出。《麓山之歌》《大山的女儿》又开始重播。"
  }
]

15. 点击加载更多

前端代码

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

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        li {
            list-style: none;
        }

        body {
            background: #eee;
        }

        .wrapper {
            background: #fff;
            width: 970px;
            margin: 20px auto;
            padding: 15px;
        }

        h1 {
            text-align: center;
            border-bottom: 1px solid #ddd;
            padding-bottom: 20px;
        }

        li {
            margin: 20px 0;
            border-bottom: 1px dotted #eee;
            padding-bottom: 20px;
        }

        p {
            line-height: 25px;
        }
    </style>
    <script src="https://libs.baidu.com/jquery/1.11.3/jquery.min.js"></script>
</head>

<body>
    <div class="wrapper">
        <h1>新闻列表(ajax点击加载更多分页)
            <script>
                document.write(new Date().toLocaleString())
            </script>
        </h1>
        <ul>

        </ul>
        <div class="footer" style="text-align: center;">
            <button id="btn" style="width: 120px; height: 60px; font-size: 20px;">加载更多</button>
        </div>
    </div>
    <script>
        let page = 1;
        let pageSize = 3;

        function getNewsList(page, pageSize) {
            $.get("http://127.0.0.1:3000/news", {
                page,
                pageSize
            }, res => {
                if (res.news.length) {
                    let str = "";
                    res.news.forEach(item => {
                        str += `
                             <li>
                                <h2>${item.title}</h2>
                                <p class="time">${item.time}</p>
                                <p class="summary">${item.summary}</p>
                            </li>
                        `
                    })
                    $("ul").append(str)
                }
            })
        }

        getNewsList(page, pageSize)

        $("#btn").click(function(e) {
            getNewsList(++page, pageSize)
        })
    </script>
</body>

</html>

后端代码同上

16. 滚动加载更多

前端代码

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

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        li {
            list-style: none;
        }

        body {
            background: #eee;
        }

        .wrapper {
            background: #fff;
            width: 970px;
            margin: 20px auto;
            padding: 15px;
        }

        h1 {
            text-align: center;
            border-bottom: 1px solid #ddd;
            padding-bottom: 20px;
        }

        li {
            margin: 20px 0;
            border-bottom: 1px dotted #eee;
            padding-bottom: 20px;
        }

        p {
            line-height: 25px;
        }
    </style>
    <script src="https://libs.baidu.com/jquery/1.11.3/jquery.min.js"></script>
    <!-- underscore中别人封装了非常多的工具函数 -->
    <!-- 其中就有节流函数:具体可以看一下每日一题 -->
    <script src="https://cdn.jsdelivr.net/npm/underscore@1.13.4/underscore-umd-min.js"></script>
</head>

<body>
    <div class="wrapper">
        <h1>新闻列表(AJAX普通分页)
            <script>
                document.write(new Date().toLocaleString())
            </script>
        </h1>
        <ul>

        </ul>
        <div class="footer" style="text-align: center;">
            <img src="" alt="" width="40px">
        </div>
    </div>
    <script>
        let page = 1;
        let pageSize = 6;
        let load = true;

        function getNewsList(page, pageSize) {
            // 开启loading效果
            $(".footer img").attr("src", "./imgs/timg.gif")

            $.get("http://127.0.0.1:3000/news", { page, pageSize }, res => {
                if (res.news.length) {
                    let str = "";
                    res.news.forEach(item => {
                        str += `
                        <li>
                            <h2>${item.title}</h2>
                            <p class="time">${item.time}</p>
                            <p class="summary">${item.summary}</p>
                        </li>
                    `
                    })
                    $("ul").append(str)
                    load = true;
                } else {
                    $(".footer").html("------------- 我是有底线 -------------")
                    load = false;
                }
            })
        }

        getNewsList(page, pageSize);

        // 当滚动滚动条时,就会触发,高频触发
        // 如何降低频率?
        // 答:节流
        // document.onscroll = function () {
        //     console.log("-------");
        // }

        // _是underscore中提供的一个对象
        // throttle  就是节流函数
        // document.onscroll = _.throttle(function () {
        //     console.log("-------");
        // }, 1000)

        document.onscroll = _.throttle(function () {
            let st = $(window).scrollTop(); // 卷上去的高度
            let ch = $(window).height(); // 一屏的高度
            let dh = $(document).height(); // 整个内容的高度
            if ((st + ch) >= (dh - 10) && load) {
                getNewsList(++page, pageSize);
            }
        }, 500)

    </script>
</body>

</html>

后端代码同上

13. 延迟时间timeout和取消请求

在网络请求的过程中,为了避免过长的时间服务器无法返回数据,通常我们会为请求设置一个超时时间:timeout

  • 当达到超时时间后依然没有获取到数据,那么这个请求会自动被取消掉
  • 默认值为0,表示没有设置超时时间
<script>
    let xhr = new XMLHttpRequest();
    xhr.open("get", "http://httpbin.org/delay/5")
    xhr.send();

    // 设置超时时间
    xhr.timeout = 3000; // 如果请求超过3秒就断开了(也就是自动取消请求)

    xhr.onload = function() {
        console.log(xhr.response);
    }
</script>
<button>取消请求</button>
<script>
    let xhr = new XMLHttpRequest();
    xhr.open("get", "http://httpbin.org/delay/5");
    xhr.send();

    // xhr.timeout = 3000; // 如果超过3秒自动取消请求

    xhr.onload = function() {
        console.log(xhr.response);
    }

    let btn = document.getElementsByTagName("button")[0];
    btn.onclick = function() {
        // 手动取消请求
        xhr.abort();
    }
</script>

二、axios

1.axios

axios是什么?

功能特点

  • 基于xhr + promise的异步ajax请求库
  • 浏览器端/node端都可以使用
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求和响应数据
  • 支持请求取消
  • 批量发送多个请求

axios请求方式

  • axios(config): 通用/最本质的发任意类型请求的方式
  • axios(url[, config]): 可以只指定url发get请求
  • axios.request(config): 等同于axios(config)
  • axios.get(url[, config]): 发get请求
  • axios.delete(url[, config]): 发delete请求
  • axios.post(url[, data, config]): 发post请求
  • axios.put(url[, data, config]): 发put请求
  • axios.defaults.xxx: 请求的默认全局配置
  • axios.interceptors.request.use(): 添加请求拦截器
  • axios.interceptors.response.use(): 添加响应拦截器
  • axios.create(config): 创建一个新的axios(它没有下面的功能)
  • axios. Cancel(): 用于创建取消请求的错误对象
  • axios. CancelToken(): 用于创建取消请求的token对象
  • axios.isCancel(): 是否是一个取消请求的错误
  • axios.all(promises): 用于批量执行多个异步请求
  • axios.spread(): 用来指定接收所有成功数据的回调函数的方法

常见的配置选项

  • 请求地址 url: ‘/user’
  • 请求类型 method: ‘get’
  • 根求路径 baseURL: ‘http://www.mt.com/api’
  • 请求前的数据处理 transformRequest:function(data){}
  • 请求后的数据处理 transformResponse: function(data){}
  • 自定义的请求头 headers:{‘x-Requested-With’:‘XMLHttpRequest’}
  • URL查询对象 params:{ id: 12 }
  • 查询对象序列化函数 paramsSerializer: function(params){ }
  • request body data: { key: ‘aa’}
  • 超时设置 timeout: 1000

2.发送request请求

前端代码

<!-- <script src="../node_modules/axios/dist/axios.min.js"></script> -->

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

<script>
    // 利用axios发请求,得到的结果是一个promise
    // 要得到成功的结果,就是需要.then
    // 真实的数据是在data中,其它的数据,都是axios帮我们封装好的
    // let axRes = axios.request({
    //     url: "http://127.0.0.1:3000/get",
    //     method: "get"
    // })
    // axRes.then(res => {
    //     console.log("data:", res.data);
    // })

    axios.request({
        url: "http://127.0.0.1:3000/get",
        method: "get"
    }).then(res => {
        console.log("data:", res.data);
    })
</script>

后端代码

const Koa = require("koa");
const cors = require("koa2-cors");
const logger = require("koa-logger");
const Router = require("@koa/router");
const koaBody = require("koa-body");
const app = new Koa();
const router = new Router();

app.use(cors());
app.use(logger());
app.use(koaBody());

router.get("/get", async (ctx, next) => {
    ctx.status = 200;
    ctx.body = "hello axios";
});

app.use(router.routes())
router.allowedMethods();

app.listen(3000, () => {
    console.log("running in http://127.0.0.1:3000");
});

3. 发送get请求

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

<script>
    // axios.get("http://127.0.0.1:3000/get").then(res => {
    //     console.log(res.data);
    // })

    (async function() {
        let res = await axios.get("http://127.0.0.1:3000/get")
        console.log(res);
    })()
</script>

后端代码同上

4. 发送get请求并传参

前端代码

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

<script>
    (async function() {
        // query传参
        // let res = await axios.get("http://127.0.0.1:3000/get?a=1&b=2")
        // console.log(res.data);

        // params传参
        let res = await axios.get("http://127.0.0.1:3000/get", {
            params: {
                name: "wc",
                age: 18,
                address: "bj"
            }
        })
        console.log(res.data);
    })()
</script>

后端代码

const Koa = require("koa");
const cors = require("koa2-cors");
const logger = require("koa-logger");
const Router = require("@koa/router");
const koaBody = require("koa-body");
const app = new Koa();
const router = new Router();

app.use(cors());
app.use(logger());
app.use(koaBody());

router.get("/get", async (ctx, next) => {
    ctx.status = 200;
    ctx.body = ctx.query;
});

router.get("/get/:name/:age/:address", ctx => {
    ctx.status = 200;
    ctx.body = ctx.params;
})

app.use(router.routes())
router.allowedMethods();

app.listen(3000, () => {
    console.log("running in http://127.0.0.1:3000");
});

5. 发送post请求

前端代码

<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
<!-- querystring -->
<script src="../node_modules/qs/dist/qs.js"></script>

<script>
    (async function() {
        // post传递参数
        // 默认是json格式传递 Content-Type: application/json;charset=UTF-8
        // let res = await axios.post("http://127.0.0.1:3000/post",{
        //     a:1,
        //     b:2,
        //     c:3
        // })
        // console.log(res.data);

        // post传递参数2
        // 设置请求头   axios配置请求头
        // axios 是一个对象,对象也叫实例
        // 默认情况下,我们可以使用人家提供给我们的实例,人家帮我们提供的实例,很多配置都是定死的
        // 我们能不能自己去创建一个实例?
        // 答:可以

        // 如果我们想自己去配置一个更加灵活的axios实例,或我需要向不同的服务器发请求?
        // 此时,我们就可以自己去创建axios实例
        let res = await axios.post("http://127.0.0.1:3000/post", qs.stringify({
            a: 1,
            b: 2
        }), {
            headers: {
                "Content-Type": "application/x-www-form-urlencoded"
            }
        })
        console.log(res.data);
    })()
</script>

后端代码

const Koa = require("koa");
const cors = require("koa2-cors");
const logger = require("koa-logger");
const Router = require("@koa/router");
const koaBody = require("koa-body");
const app = new Koa();
const router = new Router();

app.use(cors());
app.use(logger());
app.use(koaBody());

router.post("/post", async (ctx, next) => {
    ctx.status = 200;
    ctx.body = ctx.request.body;
});

app.use(router.routes())
router.allowedMethods();

app.listen(3000, () => {
    console.log("running in http://127.0.0.1:3000");
});

6. 其它

<script>
    // axios.get()
    // axios.post()
    // axios.request()
    // ....

    // axios发送多个请求
    axios.all([
        axios.get("http://httpbin.org/get"),
        axios.post("http://httpbin.org/post")
    ]).then(res => {
        console.log("res:", res);
    })
</script>
<script>
    // 设置axios的baseURL,如果设置了,后面的请求会自动添加baseURL
    let baseURL = "http://httpbin.org"
    axios.defaults.baseURL = baseURL;
    axios.defaults.timeout = 3000; // 设置超时时间  如果超时了  自动取消请求
    axios.defaults.headers = { // 给请求添加请求头
        a: 1,
        b: 2
    }

    axios.get("/get").then(res => {
        console.log("res:", res);
    })
</script>

7. axios的创建实例

为什么要创建axios的实例呢

  • 当我们从axios模块中导入对象时, 使用的实例是默认的实例
  • 当给该实例设置一些默认配置时, 这些配置就被固定下来了
  • 但是后续开发中, 某些配置可能会不太一样
  • 比如某些请求需要使用特定的baseURL或者timeout等
  • 这个时候, 我们就可以创建新的实例, 并且传入属于该实例的配置信息

面试题

  • 需求: 项目中有部分接口需要的配置与另一部分接口需要的配置不太一样, 如何处理
  • 解决: 创建2个新axios, 每个都有自己特有的配置, 分别应用到不同要求的接口请求中

注意点

  • 根据指定配置创建一个新的axios, 也就就每个新axios都有自己的配置
  • 新axios只是没有取消请求和批量发请求的方法, 其它所有语法都是一致的
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>

<script>
    // axios.get

    // 创建自己的实例  {}叫配置对象,这里面,就可以书写自己的配置
    let axios1 = axios.create({
        baseURL: "http://127.0.0.1:3000",
        timeout: 3000,
        headers: {}
    })

    axios1.get("/news", {
        params: {
            a: 1
        }
    }).then(res => {
        console.log("res:", res);
    })

    let axios2 = axios.create({
        baseURL: "http://127.0.0.1:5000",
        timeout: 5000,
        headers: {}
    })

    axios1.get("/students", {
        params: {
            a: 1
        }
    }).then(res => {
        console.log("res:", res);
    })
</script>

8. 请求和响应拦截器

axios的也可以设置拦截器:拦截每次请求和响应

  • axios.interceptors.request.use(请求成功拦截, 请求失败拦截)
  • axios.interceptors.response.use(响应成功拦截, 响应失败拦截)
    前端代码
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/nprogress/0.2.0/nprogress.min.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/nprogress/0.2.0/nprogress.min.css" rel="stylesheet">

<button>发送请求</button>

<script>
    let btn = document.querySelectorAll("button")[0];

    // 给默认实例添加请求拦截器
    // 这样写,相当于,这个拦截器什么也没有做
    // axios.interceptors.request.use(config => {
    //     return config;
    // })

    // 所谓的做一些事,就是做一些配置
    axios.interceptors.request.use(config => {

        config.headers.Authorization = `fsadfsadf6789f87s6adf68asodfihasjkdfasdf7678fasd67f8asdfas`;

        NProgress.start(); // 显示进度条

        return config;
    }, err => {
        // 失败的回调,直接响应失败的promsie
        return Promise.reject(err)
    })

    axios.interceptors.response.use(response => {

        NProgress.done(); // 关闭进度条

        return response.data; // 仅仅把data过滤出来
    }, err => {
        // 失败的回调,直接响应失败的promsie
        return Promise.reject(err)
    })

    btn.onclick = function() {
        axios.get("http://httpbin.org/delay/5").then(res => {
            console.log(res);
        })
    }
</script>

面试题:拦截器函数/ajax请求/请求的回调函数的调用顺序

  • 说明: 调用axios()并不是立即发送ajax请求, 而是需要经历一个较长的流程
  • 流程: 请求拦截器2 => 请求拦截器1 => 发ajax请求 => 响应拦截器1 => 响应拦截器2 => 请求的回调
  • 注意: 此流程是通过promise串连起来的, 请求拦截器传递的是config, 响应拦截器传递的是response

9. 取消请求

基本流程

  • 配置cancelToken对象
  • 缓存用于取消请求的cancel函数
  • 在后面特定时机调用cancel函数取消请求
  • 在错误回调中判断如果error是cancel, 做相应处理

实现功能:点击按钮, 取消某个正在请求中的请求

  • 在请求一个接口前, 取消前面一个未完成的请求
<!-- axios源码   JS高级 -->

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

<button>发送请求</button>
<button>取消请求</button>

<script>
    let btns = document.querySelectorAll("button");
    let cancel;
    // 在请求一个接口前,取消前面没有完成的请求
    btns[0].onclick = async function() {
        let result = await axios("http://httpbin.org/delay/5", {
            cancelToken: new axios.CancelToken(c => {
                cancel = c;
            })
        });

        console.log("result:", result);
    }
    btns[1].onclick = function() {
        cancel(); // 手动取消上面的请求
    }
</script>

10. Axios二次封装

功能点

  • 统一进行请求配置: 基础路径/超时时间等
  • 请求过程中loading提示
  • 请求可能需要携带token数据
  • 请求成功的value不再是response, 而是response.data
  • 请求失败/出错统一进行处理, 每个请求可以不用单独处理
<!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.min.js"></script>
    <script src="../node_modules/nprogress/nprogress.js"></script>
    <link rel="stylesheet" href="../node_modules/nprogress/nprogress.css">

    <!-- <script src="https://cdn.bootcdn.net/ajax/libs/nprogress/0.2.0/nprogress.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/nprogress/0.2.0/nprogress.min.css" rel="stylesheet"> -->
</head>

<body>

    <script>
        // 一般会自己创建一个axios实例    instance是实例的意思
        let instance = axios.create({
            // 在这里,可以做很多配置
            // baseURL是配置基础路径
            baseURL: "http://127.0.0.1:3000",
            timeout: 8000
        })

        // 目前在请求拦截器中配置了:
        //    1)开启Nprogress进度条
        //    2)在请求头中添加token
        instance.interceptors.request.use(config => {
            let token = localStorage.getItem("token") || "fasdfasdfsadf";
            config.headers["token"] = token;

            NProgress.start();

            return config;
        }, err => {
            return Promise.reject(err)
        })

        // 目前在响应拦截器中配置了:
        //    1)关闭Nprogress进度条
        //    2)过滤出data数据
        instance.interceptors.response.use(response => {

            NProgress.done();

            return response.data;
        }, err => {
            NProgress.done();
            return Promise.reject(err)
        })

        // 后面发请求,就可以使用自己的实例
        instance.get("http://httpbin.org/delay/5").then(res => {
            console.log(res);
        })
    </script>
</body>

</html>

11. JSONP原理

前端代码

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

<button id="btn">发送ajax请求</button>

<script>
    let btn = document.getElementById("btn");

    function jsonp(options) {

        let callBackName = "wangcai";

        window[callBackName] = function(data) {
            if (data != null) {
                options.success(data)
            } else {
                options.fail()
            }
        }

        let url = options.url + "?callBack=" + callBackName
        let scriptEle = document.createElement("script");
        scriptEle.src = url;
        document.body.append(scriptEle)
    }

    btn.onclick = function() {
        jsonp({
            url: "http://localhost:3000/",
            success: function(data) {
                console.log("data:", data);
            },
            fail: function(err) {
                console.log("数据请求失败了");
            }
        })
    }
</script>

后端代码

const Koa = require("koa");
const cors = require("koa2-cors");
const logger = require("koa-logger");
const Router = require("@koa/router");
const koaBody = require("koa-body");
const app = new Koa();
const router = new Router();

app.use(cors());
app.use(logger());
app.use(koaBody());

router.get("/", (ctx) => {
    let cb = ctx.query.callBack;
    // console.log(cb);

    // 后端返回函数调用字符串
    ctx.body = `${cb}(${JSON.stringify({ a: 1, b: 2 })})`
})

app.use(router.routes())
router.allowedMethods();

app.listen(3000, () => {
    console.log("running in http://127.0.0.1:3000");
});

12. 百度联想词案例

前端JS代码

;
(function() {
    // 接口地址:https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=
    let searchInput = document.getElementsByClassName("J_searchInput")[0];
    let wdList = document.getElementsByClassName("J_wdList")[0];
    let listWrap = wdList.parentNode;

    searchInput.addEventListener("input", function() {
        let val = this.value.trim();
        if (val.length > 0) {
            getDatas(val, "setDatas");
        } else {
            wdList.innerHTML = "";
            listWrap.style.display = "none";
        }
    })

    // 调接口,获取数据
    function getDatas(value, callbackName) {
        let oScript = document.createElement("script");
        oScript.src = "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=" + value + "&cb=" + callbackName
        document.body.append(oScript)
    }

    window.setDatas = function(data) {
        // console.log("data:",data);
        // render是渲染的意思  List是列表的意思
        renderList(data)
    }

    // <li class="wd-item">
    //     <a href="https://www.baidu.com/s?wd={{wdLink}}" target="_blank" class="wd-lk">{{wd}}</a>
    // </li> 

    // 渲染数据到页面上
    function renderList(data) {
        var data = data.s;
        let len = data.length;
        let list = "";

        if (len) {
            data.forEach(item => {
                list += `
                    <li class="wd-item">
                        <a href="https://www.baidu.com/s?wd=${item}" target="_blank" class="wd-lk">${item}</a>
                    </li> 
                `
            })
            wdList.innerHTML = list;
            listWrap.style.display = "block";
        } else {
            wdList.innerHTML = "";
            listWrap.style.display = "none";
        }
    }
})()

开源接口:
https://docs.tenapi.cn/
https://www.free-api.com/
https://api.aa1.cn/

ajaxaxios有什么区别和优缺点? 回答: ajaxaxios都是用于向后端发起请求的工具,但它们有一些区别和优缺点。ajax是对原生XHR的封装,是浏览器天生支持的API,可以实现局部数据的刷新。而axios是一个基于Promise的http库,通过Promise实现对ajax技术的封装,返回的数据是一个promise对象。axios功能更丰富,风格前卫,更易于使用和安全。\[1\]\[2\]此外,axios还具有一些特性,如在浏览器中创建XMLHttpRequest对象,在node.js中创建Http请求,支持拦截请求和响应,自动转换响应为JSON格式,以及提供一些并发请求的功能。\[3\]总的来说,axios相比ajax更加灵活、功能更丰富,更易于使用和安全。 #### 引用[.reference_title] - *1* *2* [ajaxaxios区别及优缺点](https://blog.csdn.net/Senora/article/details/122220983)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [ajaxaxios](https://blog.csdn.net/qq_48973567/article/details/127830858)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值