Ajax学习笔记
一、ajax简介
全称为Asynchronous JavaScript And XML,就是异步的JS和XML通过AJAX 可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据。AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。
1、XML简介
可扩展标记语言。XML被设计用来传输和存储数据。XML和HTML类似,不同的是HTML中都是预定义标签,而XML中没有预定义标签,全部都是自定义标签,用来表示一些数据。(目前已经被JSON取代)
2、ajax的特点
ajax的优点
(1)可以无需刷新页面与服务端进行通信
(2)允许你根据用户事件来更新部分页面内容
ajax的缺点
(1)没有浏览历史,不能回退
(2)存在啊跨域问题(同源)
(3)SEO不友好
二、HTTP协议
HTTP全称为hypertext transport protocol 协议【超文本传输协议】,协议详细规定了浏览器和万维网服务器之间互相通信的规则。
重点格式与参数:
1、请求报文
行:POST
/URL HTTP
协议版本
头: Host:值
Cookie: 值
Content-type:值
User-Agent:值
等等
空行:
体:如果是GET请求体为空,如果是POST可以不为空
2、响应报文
行:HTTP协议版本
响应状态码
响应状态字符串
头: Content-type:值
Content-length:值
Content-encoding:值
等等
空行:
体:HTML语法内容
三、ajax的准备工作
1、安装node.js
这一步无脑安装就可以了
2、安装express
打开文件点击终端,输入npm iexpress
3、创建一个服务端
(1)创建一个JS文件,编写四个步骤,然后在终端输入node 文件名.js
就可以启动服务
//1. 引入express
const express = require('express');
//2. 创建应用对象
const app = express();
//3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
app.get('/', (request, response) => {
//设置响应
response.send('HELLO EXPRESS');
});
//4. 监听端口启动服务
app.listen(8000, () => {
console.log("服务已经启动, 8000端口监听中....");
});
(2)然后就可以在网站上输入本机地址:8000
进行访问
(3)端口释放:Ctrl
+C
四、发送Ajax请求
1、发送GET请求
要编写两个文件,一个是前端页面的准备,一个是服务端代码的准备
前端我们设置一个按钮,点击按钮可以发送ajax请求给服务器,把请求体放到div里
<body>
<button>点击发送请求</button>
<div id="result"></div>
</body>
//获取button元素
const btn = document.getElementsByTagName('button')[0];
const result = document.getElementById("result");
//绑定事件
btn.onclick = function () {
//1. 创建对象
const xhr = new XMLHttpRequest();
//2. 初始化 设置请求方法和url
xhr.open('GET', 'http://192.168.0.102:8000/server');
//3. 发送
xhr.send();
//4. 事件绑定 处理服务端返回的结果
// on when 当...的时候
// readystate 是 xhr 对象中的属性,表示状态 0 1 2 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;
}
}
}
}
服务端server.js文件:
//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端口监听中....");
});
2、发送POST请求
POST请求这里跟GET请求不同的是,设置参数是在send方法里面设置的,可以是任意类型
const result = document.querySelector('#result');
result.addEventListener('mouseover' ,function() {
//1.创建对象
const xhr = new XMLHttpRequest();
//2.初始化 设置类型与url
xhr.open('POST','http://127.0.0.1:8000/server');
//设置请求头:固定写法,第一个参数设置请求体内容类型,第二个参数是参数查询字符串的类型
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
//3.发送请求,在这里传参,任意类型都可以
xhr.send('a=1&b=2&c=3');
// xhr.send('12241312312');
//4.绑定事件
xhr.onreadystatechange = function() {
//判断服务端是否返回所有结果
if(xhr.readyState === 4) {
//判断响应是否成功
if(xhr.status >=200 && xhr.status<300) {
//处理服务端返回的结果
result.innerHTML = xhr.response;
}
}
}
})
服务端server.js是要设置post请求
//1. 引入express
const express = require('express');
//2. 创建应用对象
const app = express();
//3. 创建路由规则
// request 是对请求报文的封装
// response 是对响应报文的封装
app.post('/server', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
//设置响应体
response.send('HELLO Ajax');
});
//4. 监听端口启动服务
app.listen(8000, () => {
console.log("服务已经启动, 8000端口监听中....");
});
##/3、设置请求头信息
在open
方法后面,send
方法前,添加xhr.setRequestHeader()
方法
xhr.open('GET', 'http://192.168.0.102:8000/server');
//设置请求头
xhr.setRequestHeader('Content-Type','application/x-ww-form-urlencoded');
//3. 发送
xhr.send();
3、响应JSON数据
假设服务端server.js有一个data数据,因为send方法里面只能接收字符串,所以我们要对data数据进行字符串转换
app.all('/json-server', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
//设置响应数据
const data = {
name: '你好zh'
};
let str = JSON.stringify(data);
//设置响应体
response.send(str);
});
页面文件我们设置一个
const result = document.getElementById("result");
//绑定键盘按下事件
window.onkeydown = function () {
//1. 创建对象
const xhr = new XMLHttpRequest();
//2. 初始化 设置请求方法和url
xhr.open('GET', 'http://192.168.0.102:8000/json-server');
//3. 发送
xhr.send();
// 事件绑定
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.response);
result.innerHTML = xhr.response;
}
}
}
}
我们可以看到已经拿到了这个data数据,但是它还是一个JSON格式的字符串,现在我们要把它提取出来,一共有两种方法:
(1)手动对数据进行转换
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status >= 200 && xhr.status < 300) {
// console.log(xhr.response);
// result.innerHTML = xhr.response;
let data = JSON.parse(xhr.response);
console.log(data);
result.innerHTML = data.name;
}
}
}
(2)自动转换
const result = document.getElementById("result");
window.onkeydown = function () {
const xhr = new XMLHttpRequest();
// 设置响应体数据的类型
xhr.responseType = 'json';
xhr.open('GET', 'http://192.168.0.102:8000/json-server');
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status >= 200 && xhr.status < 300) {
result.innerHTML = xhr.response.name;
}
}
}
}
4、Ajax请求存在的问题
(1)IE缓存问题
在IE浏览器中,他不会随着响应体的更新而更新,解决的方法就是在url后面加一个时间戳,让他知道这是不同时间发送的不同的响应体,这样问题就解决了
const btn = document.getElementsByTagName('button')[0];
const result = document.getElementById("result");
//绑定键盘按下事件
btn.addEventListener('click', function () {
const xhr = new XMLHttpRequest();
xhr.open('GET', 'http://192.168.0.102:8000/ie' + Date.now());
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status >= 200 && xhr.status < 300) {
result.innerHTML = xhr.response;
}
}
}
})
服务端server.js
app.get('/ie', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
response.send('hello ie -1');
});
//4. 监听端口启动服务
app.listen(8000, () => {
console.log("服务已经启动, 8000端口监听中....");
});
(2)Ajax请求超时与网络异常处理
在服务端写一个延时器,等过两秒在发送响应体
app.get('/delay', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
setTimeout(() => {
response.send('演示响应');
}, 3000)
});
设置超时xhr.timeout
,超时回调xhr.ontimeout
,网络异常回调xhr.onerror
const xhr = new XMLHttpRequest();
//超时设置 2s 设置
xhr.timeout = 2000;
// 超时回调
xhr.ontimeout = function(){
alert("网络异常,请稍后再试!!");
}
// 网络异常回调
xhr.onerror = function(){
alert("你的网络似乎除了一些问题!");
}
怎么体现出网络异常回调呢?
我们可以用浏览器中的手动断网
(3)Ajax取消请求
还是在服务端设置延时器
app.get('/delay', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
setTimeout(() => {
response.send('演示响应');
}, 3000)
});
设置两个按钮
<button>点击发送</button>
<button>点击取消</button>
用abort()
方法设置取消请求
const btns = document.querySelectorAll('button');
let x = null;
btns[0].onclick = function () {
x = new XMLHttpRequest();
x.open("GET", "http://192.168.0.102:8000/delay");
x.send();
}
//abort
btns[1].onclick = function () {
x.abort();
}
(3)Ajax重复请求
当重复点击发送ajax请求时,服务器的压力会很大,解决的办法就是定义一个标识变量,设置为false,当点击了发送ajax请求时,把标识变量设置为true,当readyState等于4的时候,再把标识变量变回true
const btns = document.querySelectorAll('button');
let x = null;
//标识变量
let isSending = false; // 是否正在发送Ajax请求
btns[0].onclick = function () {
// 判断标识变量
if(isSending) x.abort(); // 如果正在发送,则取消该请求,创建一个新的请求
x = new XMLHttpRequest();
// 修改 标识变量的值
isSending = true;
x.open("GET", "http://192.168.0.102:8000/delay");
x.send();
x.onreadystatechange = function () {
if (x.readyState === 4) {
// 修改标识变量
isSending = false;
}
}
}
五、nodemon自动重启工具
当我们每一次修改服务端代码时,总是要执行node 文件名.js
命令来重启,安装nodemon工具就可以去掉这个操作,它会自动重启服务,非常的便捷
在终端先执行npm install -g nodemon
,然后执行nodemon server.js
命令安装nodemon即可