原生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>
相关推荐
y先森2 小时前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy2 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189112 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿3 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡4 小时前
commitlint校验git提交信息
前端
虾球xz4 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇5 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒5 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员5 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐5 小时前
前端图像处理(一)
前端