文章目录
AJAX
释放端口 ctrl+c
自启动服务端 npx nodemon nidi.js
IE缓存问题解决:添加一个Date.now() 让它知道这是动态
XML 用来传输和保存数据(自定义标签)
目前已经被JSON取代
HTTP
超文本传输协议
HTTP请求报文格式
行 GET/POST /s?ie=utf-t(url) HTTP/1.1(版本)
头 Host: nidi.com
Cookie: name=nidi
Content-type: application/x-www-form-urlencoded
Use-Agent: chrome 83"
空行
体 GET请求体为空,POST请求体可以不为空
响应报文格式
行 HTTP协议版本 响应状态码 响应状态字符串
头
Content-type: text/html;charset=utf/8
Content-length: 2048
Content-encoding: gzip
空行
体 HTML语法内容
<html>
<head>
</head>
<body>
<h1></h1>
</body>
</html>
Express
//引入express
const express = require('express');
//创建应用对象
const app = express();
//创建路由规则
//request 是请求报文的封装
//response 是对响应报文的封装
app.get('/server', (request, response)=>{
//改成/server,当客户端浏览器发送请求时,url的路径是请求行的第二段的内容他的路径是/server,执行回调函数
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
//设置响应
response.send('hello ajax');
});
//监听端口启动服务
app.listen(8000, ()=>{
console.log("服务已经启动,8000端口监听中");
});
释放端口 ctrl+c
请求基本操作
get请求操作
get请求体放在路径后面加?即可
<body>
<button>点击提示信息</button>
<div id="result"></div>
</body>
<script>
const btn = document.getElementsByTagName('button')[0];
btn.onclick = function(){
console.log('test');
//ajax操作 响应报文
//1.创建对象
const xhr = new XMLHttpRequest();
//2.初始化 设置请求方法和url
xhr.open('GET','http:/127.0.0.1:8000/server?a=100&b=200');
//设置请求参数 ?a=100&b=200
//3.发生
xhr.send();
//4.事件绑定
//on when当..的时候
//redystate 是xhr对象中的属性
//状态0 1 2 3 4
//0 表示未初始化
//1 open方法调用完毕
//2 send方法调用完毕
//3 服务端返回了部分结果
//4 服务端返回了所有结果
//change 改变
xhr.onreadystatechange = function(){
//判断(服务端返回所有结果)
if(xhr.readyState === 4){
//判断响应状态码 200 404 403 401 500
//2xx 成功
if(xhr.status >= 200 && xhr.status < 300){
//处理结果 行 头 空行 体
//响应
// console.log(xhr.status);//状态码
// console.log(xhr.statusText);//状态字符串
// console.log(xhr.getAllResponseHeaders());//所有响应头
// console.log(xhr.response);//响应体
//设置result的文本
result.innerHTML = xhr.response;
}
}
}
}
</script>
const express = require('express');
const app = express();
app.get('/server', (request, response) => {
//当客户端浏览器发送请求时,url的路径是请求行的第二段的内容他的路径是/server,执行回调函数
response.setHeader('Access-Control-Allow-Origin', '*');
response.send('hello');
});
app.listen(8000, () => {
console.log("服务已经启动,8000端口监听中");
});
POST请求操作
鼠标经过div发送Ajax请求,将请求体显示在div中
post请求体放在send()中
<body>
<div id="result">放在上面提示信息</div>
</body>
<script>
//获取元素对象
const result = document.getElementById("result");
//绑定事件
//mouseover 当鼠标发放在上面时发送请求
result.addEventListener("mouseover",function(){
console.log("test");
//1.创建对象
const xhr = new XMLHttpRequest();
//2.初始化 设置类型与URL
xhr.open('POST', 'http://127.0.0.1:8000/server');
//设置请求体
//3.发送
xhr.send('a=100&b=200');
//post请求体放在send中
//4.事件绑定
xhr.onreadystatechange = function(){
//判断
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 300){
//处理服务端返回结果
result.innerHTML = xhr.response;
}
}
}
})
</script>
const express = require('express');
const app = express();
app.post('/server', (request, response) => {
//设置响应头 允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
//设置响应体
response.send('hello post');
});
app.listen(8000, () => {
console.log("服务已经启动,8000端口监听中");
});
响应状态码返回404的原因
1.url设置出错 (http://)
2.网络出现波动,请求错误
设置头信息
//写在open后面
//设置请求头
//Content-Type设置请求体内容类型 第二个''参数查询字符串的类型(固定写法)
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
//自定义 错误原因:在请求头中加入了自定义的头
xhr.setRequestHeader('name','nidi');
//解决方法:
//在js中加入 (设置自定义请求头服务器需设置)
//response.setHeader('Access-Control-Allow-Headers','*');
//并把类型变成all
const express = require('express');
const app = express();
app.all('/server', (request, response) => {
//设置响应头 允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
//响应头 可以自定义
response.setHeader('Access-Control-Allow-Headers','*');
//设置响应体
response.send('hello post');
});
app.listen(8000, () => {
console.log("服务已经启动,8000端口监听中");
});
服务端响应JSON数据
服务器响应也可以设置为一个数据发送过去,但是不能直接写,要通过JSON.stringify(数据)把数据转换为JSON字符串。因为resopnse.send()中只能写字符串
<div id="result">按下键盘按键反应</div>
<script>
const result = document.getElementById('result');
//绑定键盘按下事件
window.onkeydown = function(){
//发送请求
const xhr = new XMLHttpRequest();
//设置响应体数据类型
xhr.responseText = 'json';
//初始化
xhr.open('GET','http://127.0.0.1:8000/json-server');
//发送
xhr.send();
//事件绑定
xhr.onreadystatechange = function(){
if ( xhr.readyState === 4){
if ( xhr.status >= 200 && xhr.status <= 300){
// console.log(xhr.response);
// result.innerHTML = xhr.response;
//页面拿到json响应体是无法直接识别的,需要将json字符串转化为js对象
//1.手动对数据转化
// let data = JSON.parse(xhr.response);
// console.log(data);
// result.innerHTML = data.name;
//2.自动对数据转换
//借助xhr.resopnseType = 'json';
//在上面设置响应体数据类型
console.log(xhr.response);
result.innerHTML = data.name;
}
}
}
}
</script>
const express = require('express');
const app = express();
app.all('/json-server', (request, response) => {
//响应头
response.setHeader('Access-Control-Allow-Headers','*');
//响应一个数据
const data = {
name: 'nidi'
};
//对对象进行字符串转换
let str = JSON.stringify(data);
//设置响应体
response.send(str);
});
app.listen(8000, () => {
console.log("服务已经启动,8000端口监听中");
});
网络请求超时及网络异常处理
服务端写个定时器,3s之后发送给响应体
const express = require('express');
const app = express();
app.all('/delay', (request, response) => {
//响应头
response.setHeader('Access-Control-Allow-Headers','*');
//延时响应 3s做出响应
setTimeout(() => {
//设置响应体
response.send('延时响应');
}, 3000);
});
app.listen(8000, () => {
console.log("服务已经启动,8000端口监听中");
});
前端页面设置超时设置xhr.timeout = 2000
超时回调xhr.ontimeout 网络异常回调xhr.onerror
<button>点击发送</button>
<div id="result"></div>
<script>
const btn = document.getElementsByTagName('button')[0];
btn.addEventListener('click', function(){
const xhr = new XMLHttpRequest();
//超时设置 如果超时2s就取消
xhr.timeout = 2000;
//网络回调
xhr.ontimeout = function(){
alert('网络异常,请稍后重试');
}
//网络异常回调
//onerror 错误监视器
xhr.onerror = function(){
alert("你的网络似乎出了点问题");
}
xhr.open("GET",'http://127.0.0.1:8000/delay');
xhr.send();
xhr.onreadystatechange = function(){
if (xhr.readyState === 4){
if ( xhr.status >= 200 && xhr.status < 300){
result.innerHTML = xhr.response;
}
}
}
})
</script>
手动取消请求
<button>点击发送</button>
<button>取消发送</button>
<script>
const btns = document.querySelectorAll('button');
let x = null;
//发送按钮
btns[0].onclick = function(){
//发送请求
x = new XMLHttpRequest();
x.open("GET", 'http://127.0.0.1:8000/delay');
x.send();
}
//abort 借助这个来取消请求
btns[1].onclick = function(){
x.abort();
}
</script>
nidi.js
定时发送的响应体
const express = require('express');
const app = express();
app.all('/delay', (request, response) => {
//响应头
response.setHeader('Access-Control-Allow-Headers','*');
//延时响应 3s做出响应
setTimeout(() => {
//设置响应体
response.send('延时响应');
}, 3000);
});
app.listen(8000, () => {
console.log("服务已经启动,8000端口监听中");
});
请求重复发送问题
多次相同请求,只会给服务端发送一个请求
<button>点击发送</button>
<script>
const btns = document.querySelectorAll('button');
let x = null;
//标识变量
let nidi = false;//是否在发送AJAX请求
btns[0].onclick = function(){
//判断标识变量
if ( nidi) x.abort();//如果正在发送,则取消该请求,创建一个新的请求
x = new XMLHttpRequest();
//修改标识变量值
nidi = true;
x.open("GET", 'http://127.0.0.1:8000/delay');
x.send();
x.onreadystatechange = function(){
if(x.readyState === 4){
//有可能请求失败,所以不用再做判断,只要拿到结果
nidi = false;//拿到服务器的全部结果后,设置false
}
}
}
</script>
Axios发送AJAX请求
1.安装axios
npm i axios
2.在线引用
可以去BootCND上面找
< script crossorigin=“anonymous” src=“https://cdn.bootcdn.net/ajax/libs/axios/1.3.4/axios.min.js”>
配置服务器
const express = require('express');
const app = express();
//all方式 可以接受任意类型的请求
app.all('/axios-server', (request, response) => {
//设置响应头 允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
//响应头
response.setHeader('Access-Control-Allow-Headers','*');
//设置响应体
const data = {name:'nidi'};
response.send(JSON.stringify(data));
});
app.listen(8000, () => {
console.log("服务已经启动,8000端口监听中");
});
发送GET请求
const btns = document.querySelectorAll('button');
btns[0].onclick = function(){
//GET请求 决定给谁发
axios.get('http://127.0.0.1:8000/axios-server',{
//url参数
params: {
id: 100,
vip: 7
},
headers: {
name:'nidi',
age:20
}
});
}
tip:可用baseURL对url进行简化
//配置baseURL
axios.defaults.baseURL='http://127.0.0.1:8000';
axios.get('axios-server',{
});
数据返回是基于Promise的:
.then(value => {
console.log(value);
})
axios发送请求成功的值是一个封装好的响应对象
我们需要的响应数据藏在response.data中
发送POST请求
btns[1].onclick = function() {
axios.post('http://127.0.0.1:8000/axios-server', {
username: 'nidi',
password: '1234'
},{
params: {
id:100,
vip: 7
},
headers: {
height: 180,
weight: 180,
}
});
}
axios函数发送通用请求
btns[2].onclick = function (){
axios({
// 请求方法
method: 'POST',
// url
url: 'http://127.0.0.1:8000/axios-server',
// url参数
params: {
vip:10,
level:30
},
// 头信息
headers: {
a:100,
b:200
},
// 请求体
data: {
username: 'admin',
password: 'admin'
}
}).then((response) =>{
console.log(response);//全部响应结果
console.log('响应状态码:', response.status);
console.log('响应状态字符串:',response.statusText);
console.log('响应头信息:', response.headers);
console.log('响应体:', response.data);
})
}
总结
axios本质上是对原声XMLHttpRequest的封装,不需要复杂的步骤
1.创建XMLHttpRequest对象
var xhr = new XMLHttpRequest();
2.初始化,给定请求方式以及请求地址
xhr.open(“请求方式”, ulr地址);
3.发送请求
xhr.send();
4.获取服务器端给客户端的响应数据
现在只需要写axios.get或axios.post或通用请求
feth()函数发送AJAX请求
const btns = document.querySelector('button');
btns.onclick = function () {
//参数在
fetch('http://127.0.0.1:8000/fetch-server?vip=10',{
//请求方法
method:'POST',
//请求头
headers:{
name:'nidi'
},
//请求体
body:'username=nidi&&password=1234'
}).then(response => {
return response.text();
//如果服务端放回结果是json,就把text改为json,会自动解析成json对象
}).then(response =>{
console.log(response);
});
}
同源策略
网页ulr和ajax请求的目标资源的url的协议、域名、端口保持一致
违背同源策略就是跨域
//要从http://120.0.0.1:9000/home打开,这样才能做到9000端口同源
<h1>你弟啊</h1>
<button>点击获取用户数据</button>
<script>
const btn = document.querySelector('button');
btn.onclick = function(){
const x = new XMLHttpRequest();
//因为是同源策略,所有url可用简写
x.open("GET",'/data');
//发送
x.send();
x.onreadystatechange = function(){
if (x.readyState === 4){
if ( x.status >= 200 && x.status < 300){
console.log(x.response);
}
}
}
}
</script>
const express = require('express');
const app = express();
app.get('/home', (request, response) => {
response.sendFile(__dirname + '/nidi.html');
});
app.get('/data', (request, response) => {
response.send('用户数据');
});
app.listen(9000, () => {
console.log("服务已经启动,9000端口监听中");
});
解决跨域的方法
JSONP(非官方),只支持get请求
利用script标签的跨域能力来发送请求
CORS(官方),跨域资源贡献
不需要在客户端做任何操作,完成在服务器中进行处理
CORS通过设置一个响应头来告诉浏览器允许跨域
response.setHeader('Access-Control-Allow-Headers','*');
原生jsonp的实践
输入框失去焦点后,input变红,p显示文字
用户名: <input type="text" id="username">
<p></p>
<script>
//获取input元素
const input = document.querySelector('input');
const p = document.querySelector('p');
//声明handl函数
function handle(data){
input.style.border = "solid 1px #f00";
//修改p标签的提示文本
p.innerHTML = data.msg
}
//绑定事件
input.onblur = function(){
//获取用户的输入值
let username = this.value;
//向服务端发送请求检查用户名是否存在
//1.创建script标签
const script = document.createElement('script');
//2.设置标签的src属性
script.src = 'http://127.0.0.1:8000/check-username';
//3.将script插入到文档中(不插入就无法向服务端发送请求)
//把script插入到body标签的最后
document.body.appendChild(script);
}
</script>
app.all('/check-username', (request,response) => {
const data = {
exist: 1,
msg:'用户名已经存在'
};
//将数据转化为字符串
let str = JSON.stringify(data);
//返回结果
response.end(`handle(${str})`);
});
//还要再开一个8000端口