Ajax教程 1-HTTP格式简介 总目录结构 2-expr

1-HTTP格式简介

1.1-http请求报文

请求行

1
ini复制代码POST  /s?ie=utf-8  HTTP/1.1  Host: atguigu.com/

包含请求方法(get , post ...),请求URL,http协议以及版本

请求头

1
2
3
4
5
makefile复制代码Host: atguigu.com
Cookie: name=guigu
Content-type: application/x-wiww-form-urlencoded
User-Agent: chrome 83
...

格式为“属性名:属性值”,服务端据此获取客户端的信息。与缓存相关的规则信息,均包含在header中

请求体

1
ini复制代码username=admin&password=admin

param1=value1&param2=value2...的格式,承载多个请求参数的数据

1.2-http响应报文

响应行:

1
复制代码HTTP/1.1 200 OK

①报文协议及版本

②状态码及状态描述

响应头:

1
2
3
4
yaml复制代码Content-Type: text/html; charset=utf-8
Content-length: 2048
Content-encoding: gzip
...

响应报文头,也是由多个属性组成,格式为“属性名:属性值

响应体:

1
2
3
4
5
6
7
xml复制代码<html>
<head>
<body>
<h1>hello</h1>
<body>
</head>
</html>

即网页的html代码

总目录结构

以下所有的实验的目录结构如下

  • Ajax
  • 1-GET.html
  • 2-POST.html
  • 3-请求超时与网络异常处理.html
  • 4-请求取消.html
  • 5-取消重复发送请求.html
  • server.js

2-express基本使用

express是一个node.js Web 架構,链接( expressjs.com/

GET请求

使用npm下载express,命令行为:npm install express --save,创建Ajax文件夹,在里面创建1-GET.htmlserver.js

1-GET.html:

1
2
3
4
5
6
7
8
9
10
11
12
javascript复制代码    <style>
#result{
width: 200px;
height: 150px;
border: 2px solid rgb(245, 64, 230);
}
</style>

<body>
<button>get</button>
<div id="result"></div>
</body>

server.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
javascript复制代码    // 1.引入express
const express = require('express');

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

// 3.创建路由规则
// request是对请求报文的封装
// response 是对响应报文的封装
app.get('/server',(request,response) => {
// 设置响应头 允许跨域
response.setHeader('Access-Control-Allow-Origin','*')
// 设置响应体
response.send("HELLO AJAX")
})

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

在Ajax文件夹打开终端输入node server.js,终端显示 服务已经启动,8000 端口监听中… ,之后打开http://127.0.0.1:8000/server显示内容为:

HELLO AJAX

现在在1-GET.html里面添加script代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
javascript复制代码    <script>
function XH(){
var xhr = new XMLHttpRequest();
// 2.初始化,设置请求方法和url
xhr.open('GET','http://127.0.0.1:8000/server')
//3.发送
xhr.send();
// 4.事件绑定 处理服务端返回的结果
xhr.onreadystatechange = function(){
// readyState表示状态 0 1 2 3 4
// 0 UNSENT 代理被创建,但尚未调用 open() 方法。
// 1 OPENED open() 方法已经被调用。
// 2 HEADERS_RECEIVED send() 方法已经被调用,并且头部和状态已经可获得。
// 3 LOADING 下载中; responseText 属性已经包含部分数据。
// 4 DONE 下载操作已完成。
if(xhr.readyState === 4){
// 判断响应状态码(如 200 404 403 ...)
// 2xx表示成功
if(xhr.status >= 200 && xhr.status <300){
// 1.处理响应行
console.log(xhr.status);//状态码
console.log(xhr.statusText);//状态字符串
console.log(xhr.getAllResponseHeaders());//所有响应头
console.log(xhr.response);//响应体
}
}
}
}
</script>

另外给1-GET.html里面的button绑定点击事件

1
ini复制代码<button onclick="XH()">get</button>

在浏览器打开1-GET.html, 点击按钮, 控制台显示:

200

OK

content-length: 10

content-type: text/html; charset=utf-8

HELLO AJAX

GET请求的参数说明

那么在ajax如何请求参数呢?直接将xhr.open('GET','http://127.0.0.1:8000/server')
后面加上参数,即:xhr.open('GET','http://127.0.0.1:8000/server?a=100&b=200'),就会获得参数a:100,b:200

POST请求

接下来再新建2-POST.html,如下:

2-POST.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
javascript复制代码      <style>
#result{
width: 200px;
height: 100px;
border: solid 2px red;
}
</style>

<body>
<div id="result"></div>
</body>

<script>
const result = document.getElementById("result")
result.addEventListener("mouseover",function(){
const xhr = new XMLHttpRequest;
xhr.open("post","http://127.0.0.1:8000/server");
xhr.send();
xhr.onreadystatechange = function(){
result.innerHTML = xhr.response;
}
})
</script>

server.js中新增加:

1
2
3
4
5
6
javascript复制代码    app.post('/server',(request,response) => {
// 设置响应头 允许跨域
response.setHeader('Access-Control-Allow-Origin','*')
// 设置响应体
response.send("HELLO AJAX POST")
})

在浏览器打开2-POST.html,当鼠标移动进去框内时显示:

HELLO AJAX POST

POST请求的参数说明

修改2-POST.html中的xhr.send

1
2
3
4
5
6
7
javascript复制代码      // 请求体的参数发送在send方法里面,

// 方式一:
// xhr.send("a=100&b=200");

// 方式二:
xhr.send("a:100&b:200")

在post方式中请求参数在send方法中

设置请求头

2-POST.html添加

1
arduino复制代码xhr.setRequestHeader("name","lihua")

设置请求头 name:lihua, 但是打开浏览器F12->network会看见报错,原因是会检测到头信息检验是否可用。而明显这个头信息不可用

为了解决这个问题,应该将server.js中的app.post改为app.all,而且需要再新设置一个响应头response.setHeader('Access-Control-Allow-Headers','*'),这样的话就可以自定义请求头

1
2
3
4
5
6
7
8
9
javascript复制代码    // 可以接受任意类型的请求
app.all('/server',(request,response) => {
// 设置响应头 允许跨域
response.setHeader('Access-Control-Allow-Origin','*')
// 设置响应头
response.setHeader('Access-Control-Allow-Headers','*')
// 设置响应体
response.send("HELLO AJAX POST")
})

.all方法可以接受任意类型的请求

服务端响应JSON数据

修改server.js中的app.all

1
2
3
4
5
6
7
8
9
10
11
12
javascript复制代码    app.all('/server',(request,response) => {
// 设置响应头 允许跨域
response.setHeader('Access-Control-Allow-Origin','*')
// 设置响应头
response.setHeader('Access-Control-Allow-Headers','*')
const data = {
like:'football'
}
let str = JSON.stringify(data)
// 设置响应体
response.send(str)
})

添加类dataJSON.stringify(data)将类转化为JSON数据,并作为响应体发送

此时打开2-POST.html在浏览器运行中,结果为

{“like”:”football”}

为了使JSON数据转化为类数据,添加xhr.responseType = 'json',将显示结果改为:
result.innerHTML = xhr.response.like则结果为

football

也可以用JSON.parse转换为类数据

3-nodemon

使用npm install -g nodemon下载nodemon,

链接 [ www.npmjs.com/package/nod… ]

nodemon的作用是服务端直接保存代码时不用重新启动服务,服务端自动更新服务

使用nodemon server.js开启服务,修改server.js的代码

1
2
3
kotlin复制代码  const data = {
like:'football-game'
}

保存,服务端自动更新,浏览器运行2-POST.html的结果为

football-game

4-问题解决

4.1-请求超时与网络异常处理

添加页面3-请求超时与网络异常处理.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
javascript复制代码    <style>
#result{
width: 200px;
height: 100px;
border: red 2px solid;
}
</style>

<body>
<button>点击发送请求</button>
<div id="result"></div>

</body>

<script>
const btn = document.getElementsByTagName('button')[0];
const result = document.getElementById('result');
btn.addEventListener('click',function(){
const xhr = new XMLHttpRequest();
xhr.open('get','http://127.0.0.1:8000/delay')
xhr.send();


// 设置超时时间
xhr.timeout = 2000
// 设置超时回调
xhr.ontimeout = function(){
alert("请求超时,请稍后重试");
}
// 设置网络异常回调
xhr.onerror = function(){
alert("网络异常,请检查您的网络")
}


xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status <300){
result.innerHTML = xhr.response;
}
}
}
})
</script>

server.js新增代码

1
2
3
4
5
6
7
javascript复制代码    app.get('/delay',(request,response) => {
// 设置响应头 允许跨域
response.setHeader('Access-Control-Allow-Origin','*')
setTimeout(() => {
response.send('延时响应')
}, 3000);
})

新增了链接/delay, server.js中设置定时器为3s后响应,由于xhr.timeout = 2000,则响应时间超时,弹出弹窗"请求超时,请稍后重试",若网络异常,弹出弹窗"网络异常,请检查您的网络"

4.2-Ajax取消请求

新增加页面4-请求取消.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
javascript复制代码    <body>
<button>请求发送</button>
<button>请求取消</button>
</body>

<script>
const btn1 = document.getElementsByTagName("button")[0];
const btn2 = document.getElementsByTagName("button")[1];
let x;
btn1.addEventListener('click',function(){
x = new XMLHttpRequest();
x.open('get',"http://127.0.0.1:8000/delay");
x.send();
x.onreadystatechange = function(){
if(x.readyState === 4){
if(x.status >= 200 && x.status <300){
console.log("请求成功");
}
}
}
})
btn2.onclick = function(){
x.abort();
}
</script>

按下btn1则请求发送,但是有3s延迟,在此期间按下btn2则请求取消,.abort()用于取消Ajax的请求发送

4.3-解决重复发送请求问题

新增加页面5-取消重复发送请求.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
javascript复制代码    <body>
<button>发送请求</button>
</body>

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

issending = false// 标识变量 是否正在请求Ajax

btn.addEventListener('click',function(){
if(issending == true) xhr.abort();// 如果状态码为发送状态(true),则取消发送请求
issending = true;// 此时为正在发送
xhr = new XMLHttpRequest();
xhr.open('get','http://127.0.0.1:8000/delay');
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
issending = false;//发送完毕,状态码改为不在发送状态
}
}
})
</script>

在某种情况下(如:网络速度慢)用户会一直点击相同的按钮,由于连续点击按钮会持续地发送Ajax请求,当请求的速度慢或者网络卡时,会导致大量相同请求同时存在,对服务端产生压力,因此需要解决这个问题。通过设置状态码的办法,当第一次请求不成功而且第二次点击按钮的情况下,取消第一次的请求并响应第二次的请求。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%