原生Ajax及Axios、Fetch基础到进阶

一 Ajax相关知识

Ajax(Asynchronous JavaScript and XML,异步的 JavaScriopt 和 XML)是一种用于创建动态 Web 应用程序的技术,它使用 JavaScript 和 XML(或 JSON)等技术来实现异步数据传输和动态更新页面内容。

通过 Ajax 技术,可以在不刷新整个页面的情况下,向服务器发送请求,获取数据并进行处理,从而实现更加流畅、响应更快的 Web 应用程序。Ajax 技术最初是由 Google 推广的,现在已经成为了 Web 开发中不可或缺的一部分。

Ajax 的核心是 XMLHttpRequest 对象,它提供了在客户端浏览器和服务器之间发送 HTTP 请求和接收响应的功能。使用 XMLHttpRequest 对象,可以在不刷新整个页面的情况下更新部分页面内容,从而实现异步数据传输。除此之外,还可以使用 jQuery 等 JavaScript 库中提供的 Ajax 方法、Fetch API 等技术来实现 Ajax 功能。

(一) http请求响应相关

客户端和服务器

  • 客户端是向服务器发请求的。

    • 浏览器的地址栏,只能发送get请求
    • postman软件,可以各种请求,类似postman这样的软件有很多
    • a标签 img标签 link标签 script标签 form标签....
    • ajax(异步局部刷新,提升用户体验)
    • App
    • 小程序
    • ....
  • 服务器主要接收客户端的请求,给出响应。通过node的框架叫express,提供服务器功能。

url

  • 互联网上的资源都有一个url,通过url就可以定位到互联网上的某个资源。
  • 协议名称 + 主机名称 + 端口号 + 路径 + 文件 + 查询所需的字符串 + HASH
  • http:// baidu.com 8 /css/reset.css ?a=1&b=2&c=3 #abc

http:

  • HyperText Transfer Protocol 超文本传输协议。本质就是客户端和服务器之间沟通交流的规则。
  • http请求(Request):由客户端(浏览器)向服务器发出请求
  • http响应(Response):由服务器给出响应

http请求(请求报文):

  • 请求行

    • 请求方法 get post put ....
    • url 不管是什么样的请求方式,都可以通过url传递参数
    • http协议版本
  • 请求头

    • Content-Type: text/plain, application/x-www-form-urlencoded, application/json, mutipul/form-data
  • 请求体(请求正文),就是传给服务器的数据,post请求和put请求才有请求体,get请求没有请求体

http响应(响应报文):

  • 响应行
  • 响应头
  • 响应体(响应正文)

(二) 总结ajax

创建xhr对象,使用构造函数 XMLHttpRequest 就可以创建一个 XHR 对象。

csharp 复制代码
let xhr = new XMLHttpRequest();

ajax对象中的属性如下:

属性名 含义
readyState 返回一个数字,表示请求的状态: 0 -- UNSET -- XHR对象已创建或已被 abort() 方法重置。 1 -- OPENDED -- open() 方法已经被调用。 2 -- HEADERS_RECEIVED -- send() 方法已经被调用,并且响应头和响应状态已经可获得。 3 -- LOADING -- 下载中, responseText 属性已经包含部分数据。 4 -- DONE -- 所有响应数据接收完毕。
status 响应状态码,如 404、200 等。
statusText 响应状态码的文本描述/响应状态码,如 200 对应的是 "OK"。
responseXML 接收格式为 XML 的响应数据,返回一个 document 对象。
responseText 获取响应文本,返回一个字符串。
responseType 用于设置响应内容的类型 xhr2
response 返回的类型取决于 responseType 的设置。 xhr2
timeout 设置超时时间。xhr2

ajax对象中的方法如下:

方法名 含义
open() 初始化 HTTP 请求,用来指定请求方式和 URL。 xhr.open(method, url, [async], [user], [password])
send() 发送 HTTP 请求,参数可以设置请求体,没有请求体无需设置参数。
setRequestHeader() 设置 HTTP 请求头的值。必须在 open() 之后、send() 之前调用。
abort() 如果请求已被发出,则立刻中止请求。
getAllResponseHeaders() 以字符串形式返回所有的响应头。
getResponseHeader() 返回指定的响应头。

ajax对象中的事件如下:

事件名 含义
readystatechange readyState 属性值发生变化触发该事件。
abort 请求终止时触发。
error 请求遇到错误时触发。
loadstart 接收到响应数据时触发。
loadend 当请求结束(包括请求成功和请求失败)时触发,且在error、abort、load之后触发
load 请求成功完成时触发。
loaded 当请求结束时触发, 无论请求成功 ( load) 还是失败 (abor 或 error)。
progress 当请求接收到更多数据时,周期性地触发。
timeout 在预设时间内没有接收到响应时触发。

异步请求:

  • 在发请求之后,其它的同步任务都已经执行完毕了。

同步请求:

  • 在发请求之后,需要等到响应完全结束后才会执行剩下同步任务。

默认情况下,ajax发的请求,都是异步的,通过open方法中的第3个参数可以设置同步

  • true 表示异步请求 , 不写也是true
  • false 表示同步请求,基本上不用

(三) 同源策略及解决跨域问题方案

1.同源策略

同源策略是浏览器的一种安全策略,要求ajax代码所在的页面url中的协议,域名,端口与ajax请求中url中的协议,域名,端口要完全一样。举例:有一个这样的域名:www.wangcai.com

同源策略判定:

  • 源:协议 + 域名 + 端口
  • 同源:相同的协议 && 相同域名 && 相同的端口
  • 不同源:不同的协议 || 不同的域名 || 不同的端口

不受同源策略的限制情况:

  • 资源的引入 如:img标签的src link标签的href script标签的src
  • 页面中的超连接 a标签中的href
  • 表单的提交
  • 重定向页面

2.解决跨域的方案

要抵抗同源策略,叫跨域,常见解决跨域的方案:

  • cors
  • jsonp
  • 前端配置代理

cors解决跨域(后端去配置解决)

perl 复制代码
// 导入模块const path = require('path');const express = require('express');// 创建 express 实例const app = express();
app.get("/", (req, res) => {
    res.sendFile(path.join(__dirname, "../client", "index.html"))})
app.get('/getData', (req, res) => {
    console.log("来到服务器了~~")// 通过请求头,抵抗同源策略// res.set('Access-Control-Allow-Origin', 'http://localhost:3000');// res.set('Access-Control-Allow-Origin', 'http://192.168.217.1:3000');// 请允许多个域名来请求// const allowOrigins = ['http://localhost:3000','http://192.168.217.1:3000']// if (allowOrigins.includes(req.get('Origin'))) {//     res.set('Access-Control-Allow-Origin', req.get('Origin'));// }// 允许所有的域名
res. set ( 'Access-Control-Allow-Origin' , '*' );
    res.send('hello malu')});
app.listen(3000, () => {
    console.log('服务器启动了,端口是3000');})

配置好之后,即使不同源,也可以获取数据,如下:

还有一个模块,叫cors模块,使用如下:www.npmjs.com/package/cor...

JSONP(前端去做,不受同源策略的限制)

JSONP不是ajax,JSONP发请求本质是利用script标签的src发的请求

  • 前端代码:
xml 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <button id="btn">点我发请求</button>
    <div id="box"></div>
    <script>
        let btn = document.querySelector("#btn");

        // jsonp的原理
        function jsonp(options) {
            let callName = "fn";

            // data就是服务器响应的数据
            window[callName] = function (data) {
                console.log("fn函数执行了....");
                if (data != null) {
                    options.success(data)
                } else {
                    options.fail();
                }
            }

            // 利用script标签的src发请求,没有跨域问题
            // "fn(JSON.stringify({a:1,b:2}))"  
            // http://127.0.0.1:3000/?callBack=fn
            let url = options.url + "?callBack=" + callName
            let scriptEle = document.createElement("script");
            scriptEle.src = url;
            document.body.append(scriptEle)
        }

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

</html>
  • 后端代码:
javascript 复制代码
const path = require('path');
const express = require('express');

const app = express();

// http://127.0.0.1:3000/?callBack=fn
app.get("/", (req, res) => {
    let cb = req.query.callBack;
    // "fn(JSON.stringify({a:1,b:2}))"  
    res.send(`${cb}(JSON.stringify({a:1,b:2}))`)
})

app.listen(3000, () => {
    console.log('服务器启动了,端口是3000');
})

(四) 开源接口

如果请求的url,得到的是一个json数据,通常这个url叫API接口。

如下:

arduino 复制代码
https://docs.tenapi.cn/
https://www.free-api.com/
https://api.aa1.cn/

二 原生Ajax经典四步

(一) 原生Ajax经典四步

  1. 第一步:创建网络请求的AJAX对象(使用XMLHttpRequest)

    csharp 复制代码
    let xhr = new XMLHttpRequest()
  2. 第二步:监听对象状态的变化

    1. 监听XMLHttpRequest对象状态的变化
    ini 复制代码
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4) {
                console.log(xhr.response);
            }
        }
    1. 或者监听onload事件(请求完成时触发)
    ini 复制代码
        // 等价于下面这么写
        xhr.onload = () => {
            console.log(xhr.response);
        }
  3. 第三步:配置网络请求(通过open方法)

    kotlin 复制代码
    xhr.open("get", "http://127.0.0.1:3001/getData")
  4. 第四步:发送send网络请求

    1. send()参数写的是请求体 只有post请求方式才有请求体
    2. 就是给后端传递数据
    scss 复制代码
    xhr.send()

(二) 原生Ajax请求前后端代码示例

1.package.json用到的依赖

perl 复制代码
{
  "name": "code",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1"
  },
  "keywords": [],
  "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-bodyparser": "^4.4.0",
    "koa-logger": "^3.2.1",
    "koa-static": "^5.0.0",
    "koa2-cors": "^2.0.6",
    "moment": "^2.30.1",
    "mongodb": "^4.4.0",
    "nprogress": "^0.2.0",
    "qs": "^6.10.2"
  },
  "author": "",
  "license": "ISC"
}

2.前端代码:发送Ajax请求

xml 复制代码
<script>
    // 第一步:创建网络请求的AJAX对象(使用XMLHttpRequest)
    let xhr = new XMLHttpRequest()
    // 第二步:监听XMLHttpRequest对象状态的变化,或者监听onload事件(请求完成时触发)
        // 方式一 onreadystatechange
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4) {
                console.log(xhr.response);
            }
        }
        // 方式二 onload
        // xhr.onload = () => {
        //     console.log(xhr.response);
        // }
        
    // 第三步:配置网络请求(通过open方法)
    xhr.open("get", "http://127.0.0.1:3001/getData")

    // 第四步:发送send网络请求
    xhr.send()
</script>

3.后端代码:监听到后接收请求并响应

ini 复制代码
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());

// 写了一个接口  请求方式是get  请求的api是/getData
// 请求返回的状态码是200  返回的结果是helloajax
router.get("/getData", async (ctx, next) => {
    ctx.status = 200
    ctx.body = "helloajax"
})

app.use(router.routes())
//允许任意方式发送的请求
router.allowedMethods()
//监听端口
app.listen(3001,()=>{
    console.log("服务器跑起来了");
})

三 处理后端响应的数据

(一) 后端相应json数据

  • 前端设置:xhr.responseType = 'json' 将得到的json串转成对象
  • 后端设置:ctx.type = "json"

1.前端代码:发送ajax请求

xml 复制代码
<script>
    // 1)创建对象
    let xhr = new XMLHttpRequest()
    // 2)绑定load事件
    xhr.onload = function () {
        // 在network面板中 找到响应头,看到响应的数据类型是:
        // Content-Type:application/json; charset=utf-8
 console . log (xhr. response ); //从{"name":"哈哈"}变成{name:"哈哈"}
    }
 // 可以通过xhr.responseType这种方式,将得到的json串转成对象
xhr. responseType = 'json'
    // 3)配置网络请求
    xhr.open('get', 'http://127.0.0.1:3001/json')
    // 4)发送请求
    xhr.send()

</script>

2.后端代码:监听到后接收请求并响应json格式数据

ini 复制代码
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) => {
    ctx.status = 200
ctx. type = "json"
ctx. body = {
 name : "哈哈"
 //无论是json格式还是对象格式都会被浏览器自动转为json格式传输,所以都可
 //"name": "哈哈"
}
})

app.use(router.routes())

router.allowedMethods()

app.listen(3001, () => {
    //启动服务器并监听特定端口的方法
    console.log("服务器跑起来了");
})

(二) 后端响应xml的数据

  • 前端设置:xhr.responseType = 'json' 将得到的json串转成对象
  • 后端设置:ctx.type = "xml"

1.前端代码:发送ajax请求

xml 复制代码
<script>
    let xhr = new XMLHttpRequest()
    xhr.onload = () => {
 //用xhr.responseXML获取返回数据,不用xhr.response
        console.log(xhr. responseXML);
    }
    xhr.open("get", "http://127.0.0.1:3001/xml")
    xhr.send()
</script>

2.后端代码:监听到后接收请求并响应xml格式数据

ini 复制代码
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) => {
    ctx.status = 200
ctx. type = "xml"
ctx. body = `
<content>
<name>哈哈</name>
</content>`
})

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

app.listen(3001, () => {
    console.log("服务器跑起来了");
})

四 前端发送请求传递参数/数据

(一) get传参(通过url传参)

1.方式一: query

前端传参:xhr.open('get', 'http://127.0.0.1:3002/getData ? name **=**zhangsan & address=zz')

后端获取:router.get("/getData", (ctx) => {}

ctx.query

2.方式二: params

看network面板:通过params传参 并没有payload选项

前端传参:xhr.open("get", "http://127.0.0.1:3002/getData /zhangsan/18")

后端获取:router.get("/getData /:name/:age", (ctx) => {}

ctx.params

3.代码示例

  1. 前端代码
xml 复制代码
<script>
    let xhr = new XMLHttpRequest()
    xhr.onload = () => {
        console.log(xhr.response);
    }
    xhr.responseType = "json"
    // ----------------------------------------------------
    // get传参的第一种方式: 通过query传参
    xhr.open('get', 'http://127.0.0.1:3002/getData?name=zhangsan&address=zz')

    // 重点: 看network面板
    // 请求地址b:Request URL:http://127.0.0.1:3000/get?name=zhangsan&age=18&address=zz

    // 在network里面,有一个payload,表示传递给服务器的参数
    // payload -- Query String Parameters 查询字符串
    // view source: 查看参数的源码 
    // view parsed: 解析参数   name=zhangsan&age=18&address=zz

    // 注意:前端给后端传递的数据非常重要 如果你调用接口失败了,你要考虑是否是你的参数传递问题
    // ----------------------------------------------------
    // get传参的第二种方式: 通过params传参
    // 看network面板:通过params传参 并没有payload选项
    // xhr.open("get", "http://127.0.0.1:3002/getData/zhangsan/18")

    xhr.send()
</script>
  1. 后端代码
ini 复制代码
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());

// get -- query传参
router.get("/getData", (ctx) => {
    ctx.status = 200
    // 前端请求服务器传递的参数 后端又响应给我们
    ctx. body = ctx. query
    console.log(ctx.query.name);
})

// get -- params传参 动态路由
// router.get(" /getData/:name/:age", (ctx) => {
//     ctx.status = 200
//     // 前端请求服务器传递的参数 后端又响应给我们
//     ctx.body = ctx.params
// })

app.use(router.routes())
router.allowedMethods();
app.listen(3002, () => {
    console.log("running in http://127.0.0.1:3002");
})

(二) post传参(通过send(请求体))

默认情况下,看network面板中,请求头request Header里面 有一个

Content-Type:text/plain;charset=UTF-8 -- 表示给服务器默认传递的是纯文本的参数类型

再看payload,里面显示的是 Request Payload

name=zhangsan&age=18&address=zz

但是在开发中,需要传递json格式

1)x-www-form-urlencode

2)json

3)formdata

还有mutipul/form-data

0.post传参的几种格式

get请求只能通过url把数据扔给服务器,post,put请求可以不仅可以通过url把数据扔给服务器,也可以通过请求体把数据扔给服务器。把数据通过请求体扔给服务器,也是有多个格式的:

  • text/plain

    • 默认的请求体类型,如果不设置请求头字段 Content-type,默认就是该种类型
    • 求体只要是字符串就可以,后端不会做任何处理
  • application/x-www-form-urlencoded

    • 需要设置请求头 xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    • 要求请求体是查询字符串,如 a=100&b=200
    • 点击提交按钮提交表单(非Ajax),如果 Method 是 Post,默认请求体内容就是 x-www-form-urlencoded
  • application/json

    • 设置设置请求头 xhr.setRequestHeader('Content-type', 'application/json');
    • 要求请求体是 json 格式的字符串
  • multipart/form-data

1.传递"name=zhangsan&age=18"类型数据(setRequestHeader)

前端传参:

xhr.open("post", "http://127.0.0.1:3002/postData")

设置请求头:xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')

请求头一定要在 open() 之后,send() 之前设置

xhr.send("name=zhangsan&age=18&address=zz")

后端获取:ctx.request.body

代码示例:

  1. 前端代码
xml 复制代码
<script>
    let xhr = new XMLHttpRequest()
    xhr.onload = () => {
        console.log(xhr.response);
    }
    xhr.responseType = "json"
    xhr.open("post", "http://127.0.0.1:3002/postData")
   xhr. setRequestHeader ( 'Content-Type' , 'application/x-www-form-urlencoded' )
    // post传参 需要把参数放在请求体中
    // send('请求体')
xhr. send ( "name=zhangsan&age=18&address=zz" )
</script>
  1. 后端代码
ini 复制代码
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("/postData", (ctx) => {
    ctx.status = 200
    // 接受post传递过来的数据
ctx. body = ctx. request . body
    console.log(ctx.request.body.name);
})

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

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

2.传递json数据(setRequestHeader)

前端传参:

xhr.open("post", "http://127.0.0.1:3002/postData")

设置请求头:xhr.setRequestHeader('Content-Type', 'application/json')

xhr.send(JSON.stringify({ name: "zhangsan", age: 18 }))

后端获取:ctx.request.body

代码示例:

  1. 前端代码
xml 复制代码
<script>
    let xhr = new XMLHttpRequest()
    xhr.onload = () => {
        console.log(xhr.response);
    }
    xhr.responseType="json"
    xhr.open("post", "http://127.0.0.1:3001/postData")
    // 设置请求头
    // application / json  表示以json形式传递 
xhr. setRequestHeader ( 'Content-Type' , 'application/json' )
xhr. send ( JSON . stringify ({ name : "zhangsan" , age : 18 }))
</script>
  1. 后端代码:同上

2.传递formData数据(FormData)

请求体(send()的方法的参数)除了是字符串,也可以是 formData 对象。如果请求体是 FormData 对象,浏览器会自动设置请求头字段 Content-type 为 multipart/form-data。

FormData不仅可以传递普通数据,还可以上传文件。

a. 传递普通数据

前端传参:

xhr.open("post", "http://127.0.0.1:3002/postData")

let formData = new FormData(formEle) 容器 -- formEle元素的数据

xhr.send(formData)

PS:payload的view source跟其他不同

后端获取:ctx.request.body

代码示例:

  1. 前端代码
xml 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
 <!-- form表单有默认的提交事件 -->
 <!-- onsubmit="return false" 阻止默认事件的 -->
    <form onsubmit="return false" class="info">
        <input type="text" name="username">
        <input type="text" name="pwd">
    </form>
    <button class="send">发送请求</button>
</head>

<body>
    <script>
        let formEle = document.querySelector(".info")
        let btnEle = document.querySelector(".send")
        btnEle.onclick = function () {
            let xhr = new XMLHttpRequest()
            xhr.responseType = "json"
            xhr.onload = () => {
                console.log(xhr.response);
            }
            xhr.open("post", "http://127.0.0.1:3001/postData")
 // 容器 -- formEle元素的数据
 // 创建formData容器时,传递一个formDOM元素
 // 自动将form元素中的表单控制添加到formData中
 let formData = new  FormData (formEle)
 // send中不只可以放字符串,还可以放formdata对象
xhr. send (formData)
        }
    </script>
</body>

</html>
  1. 后端代码:同上

b. 上传文件

(三) 非ajax用form表单发送请求传递参数/上传数据

五 基于Ajax封装的Axios请求方法(常用)

(一) Axios 介绍

Axios 是前端最流行的 ajax 请求库 ,没有之一,react、vue官方都推荐使用 的 Ajax 请求库。

PS:与ajax、fetch相比,请求体不需用JSON.stringify()方法从对象转为json字符串

1.Axios特点

  • 基于 XMLHttpRequest + Promise 的异步的 Ajax 请求库
  • 浏览器端、Node端都可以使用
  • 支持请求和响应拦截器
  • 支持请求取消
  • 批量发送多个请求
  • 支持请求与响应的数据转换(二次封装)

2.Axios引入方式

xml 复制代码
<script src="axios脚本文件地址"</script>//下载后在页面引入
xml 复制代码
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"</script>//CDN

(二) Axios的基本使用

1. async await等方式使用Axios(简单--但是需注意使用限制)

由于async/await 是ECMAScript 2017中的一部分,而且在IE和一些旧的浏览器中不支持,所以使用时务必要小心。

  • axios(config): 通用/最本质的发送意类型请求的方式。
  • axios(url, config): 第一个参数是地址,第二个参数是配置项。
  • 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.patch(url[, data[, config]]) 发送patch请求
javascript 复制代码
 // 简单但有限制方式-async await方式   axios.get()
async function getUser() {   try {     const response = await axios. get ( '/user?ID=12345' );    console.log(response);   } catch (error) {     console.error(error);   } }

// 稍麻烦但无限制方式-promise.then()方式  axios.get().then()
axios. get ( '/user?ID=12345' )
  . then(function (response) {
    // 处理成功情况
    console.log(response);
  })
  . catch(function (error) {
    // 处理错误情况
    console.log(error);
  })
  . finally(function () {
    // 总是会执行
  });
  
  // 上述请求也可以按以下方式完成(可选)
axios.get('/user', {
    params: {
      ID: 12345
    }
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  })
  .finally(function () {
    // 总是会执行
  });  

2. 更多方式使用Axios(麻烦)

xml 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
 <!--引入axio-->
 < script  src = "https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js" ></ script >
</head>
<body>
    <button id="btn">使用axios发请求</button>
    <script>
        const btn = document.querySelector("#btn");

        btn.onclick = async function(){
         // 使用方式零   async await 方式(简单但有限制)
 const res = await axios. get ( "https://tenapi.cn/v2/toutiaohot" )
            // const res = await axios.get("/toutiaohot",{
            //     baseURL:"https://tenapi.cn/v2",
            //     timemout:5000
            // })
            console.log(res);
            
 // 使用方式零点五  axios.get()  axios.post() (稍复杂但无限制)
            // axios.get("/toutiaohot",{
            //     baseURL:"https://tenapi.cn/v2",
            //     timemout:5000
            // }).then(res => {
            //     console.log(res);
            // }).catch(reason => {
            //     console.log('请求失败!', reason);
            // });
            
            // 使用方式一  axios函数使用一个对象作为参数
            // axios({
            //     method:"GET",
            //     url:'https://tenapi.cn/v2/toutiaohot'
            // }).then(res => {
            //     console.log(res);
            // }).catch(reason => {
            //     console.log('请求失败!', reason);
            // });

            // 使用方式二  第一个参数是url,第二个参数是请求配置对象
            // axios("/toutiaohot",{
            //     method:"GET",
            //     baseURL:"https://tenapi.cn/v2",
            //     timemout:5000
            // }).then(res => {
            //     console.log(res);
            // }).catch(reason => {
            //     console.log('请求失败!', reason);
            // });

            // 使用方式三  axios.request() 方法同 axios 本身
            // axios.request("/toutiaohot",{
            //     method:"GET",
            //     baseURL:"https://tenapi.cn/v2",
            //     timemout:5000
            // }).then(res => {
            //     console.log(res);
            // }).catch(reason => {
            //     console.log('请求失败!', reason);
            // });


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

(三) Axios请求配置项

1.常用的请求配置项

url、method、baseURL、headers、data、timeout、responseType

注意:

上面那些配置项全部适用于axios(config)方法

但使用 axios.post( url , data, config)等 方法时

  • 作为请求体data不写在配置项config里,而在外面
  • url也是
perl 复制代码
{
  // `url` 是用于请求的服务器 URL
   url: '/user',
   // `method` 是创建请求时使用的方法
   method: 'get', // default
   // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
   // 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
   baseURL: 'https://some-domain.com/api/',
 // `headers` 是即将被发送的请求头
   headers: {
     'Content-type': 'appliation/json'
     },
 // `data` 是作为请求主体被发送的数据
 // 只适用于这些请求方法 'PUT', 'POST', 和 'PATCH'
 // 在没有设置 `transformRequest` 时,必须是以下类型之一:
 // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
 // - 浏览器专属:FormData, File, Blob
 // - Node 专属: Stream
     data: {
        firstName: 'Fred'
     },
  // `timeout` 指定请求超时的毫秒数(0 表示无超时时间)
  // 如果请求话费了超过 `timeout` 的时间,请求将被中断
      timeout: 1000,
  // `responseType` 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
      responseType: 'json', // default
}
  • 每次发送请求时设置配置项
scss 复制代码
axios({
    配置项...});
axios(url, {
    配置项...});
axios.get(url, {
    配置项...});
axios.post(url, data, {
    配置项...});
  • 设置全局配置项,将被应用到每一个请求。
ini 复制代码
axios.defaults.baseURL = "http://api.example.com";
axios.defaults.timeout = 2000;
axios.defaults.headers = {token:"abc",a:1,b:2}

2.代码示例

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>

<body>
    <button id="btn1">get</button>
    <button id="btn2">post</button>
    <button id="btn3">put</button>
    <button id="btn4">delete</button>
    <script>
        const btn1 = document.querySelector("#btn1");
        const btn2 = document.querySelector("#btn2");
        const btn3 = document.querySelector("#btn3");
        const btn4 = document.querySelector("#btn4");

        // 做全局配置
        axios.defaults.baseURL = "http://localhost:3000"
        axios.defaults.timeout = 5000;
        axios.defaults.headers.token = "xxxx";  // 不用管

        // get
        btn1.onclick = function () {
            // axios.get("/users?a=1&b=2").then(res => {
            axios.get("/users", {
                params: { name: "malu" }  // 也是配置问号传参
            }).then(res => {
                console.log(res.data);
            }).catch(reason => {
                console.log('请求失败:', reason);
            })
        }
        // post
        btn2.onclick = function () {
            // Content-Type: application/json
            let user = {
                id: 3,
                name: "xq"
            };
            // axios.post中第二个参数是请求体, 第三个参数是配置对象
            // 传递的参数的类型是:Content-Type: application/json
            // 不需要通过JSON.stringify包了
            axios.post("/users", user, {}).then(res => {
                console.log(res.data);
            }).catch(reason => {
                console.log('请求失败:', reason);
            })
        }
        // put
        btn3.onclick = function () {
            let user = {
                name: "malu666"
            };
            axios.put("/users/1", user, {}).then(res => {
                console.log(res.data);
            }).catch(reason => {
                console.log('请求失败:', reason);
            })
        }
        // delete
        btn4.onclick = function () {
            axios.delete("/users/3").then(res => {
                console.log(res.data);
            }).catch(reason => {
                console.log('请求失败:', reason);
            })
        }
    </script>
</body>

</html>

六 浏览器自带的Fetch请求方法(不常用)

Fetch API 被设计用来取代 XMLHttpRequest,它提供了许多与 XMLHttpRequest 相同的功能,但被设计成更具可扩展性和高效性。

Fetch API 的主要特点包括:

  1. Promise 风格的 API:Fetch API 提供了 Promise 风格的 API,可以更加方便地处理异步请求和响应。
  2. 更加灵活的请求和响应:Fetch API 可以发送任何类型的请求,包括 GET、POST、PUT、DELETE 等,也可以接收任何类型的响应,包括文本、JSON、二进制数据等。
  3. 更加强大的响应处理:Fetch API 提供了一系列的响应处理方法,包括 json()、text()、blob()、arrayBuffer() 等,可以更加方便地处理响应数据。

(一) 主要步骤

  1. 发送fetch请求

const res = await fetch( "httpbin.org/get?a=1" )

  1. 把返回的ReadableStream可读流处理成json数据

const data = await res.json() ;

另:fetch()、res.json()都返回promise对象

get,post,put,delete请求区别:

get默认,而其他发送其他方式请求需要设置配置项如请求方式method、请求体body

javascript 复制代码
            const res = await fetch("http://httpbin.org/put", {
 method : "put" , // 修改数据
 headers : {
 'Content-type' : 'application/json' ,
},
 body : JSON . stringify (user)
} )

(二) 代码示例

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

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

<body>
    <!-- fetch为浏览器自带方法,所以不需要引入组件啥的 -->

    <!-- CRUD   增删改查 -->
    <button id="btn1">get请求</button>
    <button id="btn2">post请求</button>
    <button id="btn3">put请求</button>
    <button id="btn4">delete请求</button>
    <script>
        let btn1 = document.querySelector("#btn1");
        let btn2 = document.querySelector("#btn2");
        let btn3 = document.querySelector("#btn3");
        let btn4 = document.querySelector("#btn4");

        // get请求--(默认method: "get")
        btn1.onclick = async function () {
            // fetch()、res.json()都返回promise对象
 const res = await  fetch ( "http://httpbin.org/get?a=1" )
            // 把返回的ReadableStream可读流处理成json数据
 const data = await res. json ();
            console.log(data);
        }

        // post请求
        btn2.onclick = async function () {
            let user = { name: "malu", age: 10, sex: "man", score: { chinese: 110, maths: 90, english: 88 } }
            const res = await fetch("http://httpbin.org/post", {
 method : "post" ,
 headers : {
 'Content-type' : 'application/json' ,
},
 body : JSON . stringify (user)
            })
            const data = await res.json()
            console.log("data:", data)
        }
        // put请求
        btn3.onclick = async function () {
            let user = { id: 1, name: "malu", age: 10, sex: "woman", score: { chinese: 66, maths: 44, english: 99 } }
 const res = await  fetch ( "http://httpbin.org/put" , {
 method : "put" , // 修改数据
 headers : {
 'Content-type' : 'application/json' ,
},
 body : JSON . stringify (user)
})
            const data = await res.json()
            console.log("data:", data)
        }
        // delete请求(这个是假的接口跑不通,只做写法演示)
        btn4.onclick = async function () {
 const res = await  fetch ( "http://httpbin.org/delete/1" , {
 method : "delete" ,
 headers : {
 'Content-type' : 'application/json' ,
}
})
 const data = await res. json ()
            console.log("data:", data)
        }
    </script>
</body>

</html>

七 案例:检测用户是否存在

(一) 原生Ajax方法解决

1.前端代码

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <h1>用户注册</h1>
    <form>
        <ul>
            <li>用户名:<input type="text" name="username" id="user">
                <span id="msg"></span>
            </li>
            <li>密码:<input type="text" name="pws"></li>
            <li>确认密码:<input type="text" name="pws"></li>
            <li><input type="submit" value="注册"></li>
        </ul>
    </form>
    <script>
        // 获取元素
        let unameEle = document.getElementById("user")
        let msg = document.getElementById("msg")
        // 绑定失焦事件
        unameEle.onblur = function () {
            // 获得用户名值
            //let uname = unameEle.value.trim()
            let uname = this.value.trim();
            //console.log(uname);

            // 发送请求
            // 声明ajax对象
            let xhr = new XMLHttpRequest()
            // 监听onload状态
            xhr.onload = () => {
                // 如果返回true--用户名可用
                msg.textContent = xhr.response.msg
                msg.style.color = xhr.response.msgColor
            }
            // 后台Boolean类型传到前端变字符串类型,需设置xhr.responseType = "json"
            // 从json串转为对象
            xhr.responseType = "json"
            // post版本
            // 配置请求,传递参数
            xhr.open("post", `http://127.0.0.1:3001/check`)
            // 设置请求头,请求参数为x-www-form的格式
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
            // 发送请求
            xhr.send(`uname=${uname}`)
            
            // get版本
            // 配置请求,传递参数
            // xhr.open("get", `http://127.0.0.1:3001/check?uname=${uname}`)
            // 发送请求
            // xhr.send()
        }
    </script>
</body>

</html>

2.后端代码

javascript 复制代码
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 userData = ["wc", "xq", "admin"];

// post版本
router.post("/check", (ctx) => {
  ctx.status = 200
  ctx.type = 'json'
  // 如果在users中找到相同的则返回该用户名已经被注册
  console.log(ctx.request.body.uname);
  if (userData.includes(ctx.request.body.uname)) {
    ctx.body = {
      code: 0,
      msg: "用户名已被占用",
      msgColor: "red"
    }
    // 反之
  } else {
    ctx.body = {
      code: 1,
      msg: "用户名可用",
      msgColor: "green"
    }
  }
})

// get版本
// 需求:如果在users中找到相同的则返回该用户名已经被注册,反之
// router.get("/check", (ctx) => {
//   ctx.type = 'json'
//   // console.log(ctx.query.name.trim());
//   // 如果在users中找到相同的则返回该用户名已经被注册
//   if (userData.includes(ctx.query.name.trim())) {
//     ctx.body = {
//       code: 0,
//       msg: "用户名已被占用",
//       msgColor: "red"
//     }
//     // 反之
//   } else {
//     ctx.body = {
//       code: 1,
//       msg: "用户名可用",
//       msgColor: "green"
//     }
//   }
// })

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

app.listen(3001, () => {
  console.log("服务器启动");
})

(二) Axios方法解决

仅修改部分前端代码(后端代码不变)

xml 复制代码
    <script>
        // 获取元素
        let unameEle = document.getElementById("user")
        let msg = document.getElementById("msg")
        // 绑定失焦事件
        unameEle.onblur = async function () {
            // 获得用户名值
            let unameValue = this.value.trim();
 // 用Axios发送请求
 let uname = { uname : unameValue }
 const res = await axios. post (
 "http://127.0.0.1:3001/check" ,
uname,
{
 headers : {
 'Content-type' : 'application/json'
},
 // 默认
 // responseType: 'json'
}
);
            // 修改样式
 // 只有Axios返回值套了一层data
            msg.textContent = res. data . msg
            msg.style.color = res. data . msgColor
        }
    </script>

(三) Fetch方法解决

仅修改部分前端代码(后端代码不变)

xml 复制代码
   ...
   <script>
        // 获取元素
        let unameEle = document.getElementById("user")
        let msg = document.getElementById("msg")
        // 绑定失焦事件
        unameEle.onblur = async function () {
            // 获得用户名值
            let unameValue = this.value.trim();
 // 用Fetch发送请求
 let uname = { uname : unameValue }
 const res = await  fetch ( "http://127.0.0.1:3001/check" , {
 method : "post" ,
 headers : {
 'Content-type' : 'application/json'
},
 body : JSON . stringify (uname)
})
 const data = await res. json ()
            
            // 修改样式
            msg.textContent = data. msg
            msg.style.color = data. msgColor
        }
    </script>
相关推荐
以对_11 分钟前
uview表单校验不生效问题
前端·uni-app
程序猿小D1 小时前
第二百六十七节 JPA教程 - JPA查询AND条件示例
java·开发语言·前端·数据库·windows·python·jpa
奔跑吧邓邓子2 小时前
npm包管理深度探索:从基础到进阶全面教程!
前端·npm·node.js
前端李易安2 小时前
ajax的原理,使用场景以及如何实现
前端·ajax·okhttp
汪子熙2 小时前
Angular 服务器端应用 ng-state tag 的作用介绍
前端·javascript·angular.js
Envyᥫᩣ3 小时前
《ASP.NET Web Forms 实现视频点赞功能的完整示例》
前端·asp.net·音视频·视频点赞
Мартин.7 小时前
[Meachines] [Easy] Sea WonderCMS-XSS-RCE+System Monitor 命令注入
前端·xss
昨天;明天。今天。8 小时前
案例-表白墙简单实现
前端·javascript·css
数云界8 小时前
如何在 DAX 中计算多个周期的移动平均线
java·服务器·前端
风清扬_jd8 小时前
Chromium 如何定义一个chrome.settingsPrivate接口给前端调用c++
前端·c++·chrome