根据视频进行整理
【https://www.bilibili.com/video/BV1WC4y1b78y?p=1】
视频资料
百度网盘:
链接:【https://pan.baidu.com/s/1nYiBc4hKzs8sYvAT5BZEZw】
提取码:1234
文章目录
- 1. AJAX 简介
- 2. XML 简介
- 3. AJAX 的特点
- 3.1 AJAX 的优点
- 3.2 AJAX 的缺点
- 4. HTTP 协议
- 4.1 请求报文
- 4.2 响应报文
- 4.3 浏览器中查看请求信息
- 5. Node.js
- 6. Express
- 7. 发送GET请求
- 7.1 GET请求设置参数
- 8. 发送POST请求
- 8.1 POST设置请求体
- 8.2 设置请求头
- 9. 服务端响应JSON格式的数据
- 9.1 服务端返回的JSON自动转化
- 10. nodemon
- 11. 解决 IE 缓存问题
- 12. 请求超时
- 13. 网络异常
- 14. 放弃请求
- 15. 重复发送请求问题
- 16. jQuery 发送 AJAX 请求
- 17. axios 发送请求
- 18. fetch 发送请求
- 19. 跨域 -- cors
- 19.1 cors
- 19.2 CORS 的使用
- 19.3 jsonp
AJAX 全称为 Asynchronous JavaScript And XML,就是异步的 JS 和 XML。
通过 AJAX 可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据。
AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。
XML 可扩展标记语言。
XML 被设计用来传输和存储数据。在早期,AJAX使用XML进行数据传输,现在被JSON取代。
XML 和 HTML 类似,不同的是 HTML 中都是预定义标签(官方提前制定好的),而 XML 中没有预定义标签, 全都是自定义标签,用来表示一些数据。
比如,有一个学生数据:
name = "孙悟空" ; age = 18 ; gender = "男" ;
用 XML 表示:
<student>
<name>孙悟空name>
<age>18age>
<gender>男gender>
student>
用 JSON 表示:
{
"name":"孙悟空",
"age":18,
"gender":"男"
}
HTTP(hypertext transport protocol)协议:
超文本传输协议,详细规定了浏览器和万维网服务器之间互相通信的规则。就是浏览器和服务器之间进行通讯的一种约定和规则。
HTTP协议:
通过浏览器向服务器发生请求报文和服务器向浏览器返回响应报文的方式,进行浏览器和服务器之间的通讯和数据传输。
请求报文包括:
响应报文包括:
【Node.js----Node.js概述与安装和运行】
在Node.js环境下运行js文件(一定要在文件对应的位置运行)
node js文件名
【Express】
// 导入express
const express = require('express')
// 创建应用对象
const app = express()
// 创建路由对象
// request 是对请求报文的封装
// response 是对响应报文的封装
app.get('/', (request, response) => {
// 向客户端发送数据
response.send( 'Hello from express' )
})
// 启动服务器进行监听
// 8000 端口 服务端在8000端口监听客户端向8000端口发送过来的请求
app.listen(8000, () => {
console.log('服务端在8000端口监听')
} )
app.get('/server', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
...
});
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Documenttitle>
<style>
#result {
width: 200px;
height: 100px;
border: solid 1px #90b;
}
style>
head>
<body>
<button>发送GET请求button>
<div id="result">div>
<script>
// 获取按钮
const btn = document.querySelector('button')
// 获取div
const div = document.querySelector('div')
// 绑定事件
btn.addEventListener( 'click', function() {
// 创建发送AJAX请求的对象
const xhr = new XMLHttpRequest()
// 初始化
// 设置请求的方法和url
xhr.open( 'GET', 'http://127.0.0.1:8000/' )
// 发送请求
xhr.send()
// 处理返回的数据
// on 当...时候
// readystate xhr 对象中的属性, 表示状态 0(未初始化的状态) 1(open方法调用完毕) 2(send方法调用完毕) 3(服务端返回部分结果) 4(服务端返回全部结果)
// change 改变
// 当状态改变会触发
xhr.onreadystatechange = function() {
// 服务端返回了所有的结果
if ( xhr.readyState===4 ) {
// 响应状态码 2xx 为成功
if ( xhr.status>=200 && xhr.status<300 ) {
// 返回的响应状态码
console.log(xhr.status)
// 返回的响应状态字符串
console.log(xhr.statusText)
// 返回的所有响应头
console.log(xhr.getAllResponseHeaders)
// 响应体(返回的数据)
console.log(xhr.response)
// 设置div中的文本
div.innerHTML = xhr.response
}
}
}
} )
script>
body>
html>
在请求地址url后加上?
,后面再加上 参数名=参数值&参数名=参数值&...
,&为参数之间分隔
// 绑定事件
btn.addEventListener( 'click', function() {
// 创建发送AJAX请求的对象
const xhr = new XMLHttpRequest()
// 初始化
// 设置请求的方法和url
xhr.open( 'GET', 'http://127.0.0.1:8000/?name=zs&age=18' )
...
})
服务端:
// 导入express
const express = require('express')
// 创建应用对象
const app = express()
// 创建路由对象
// request 是对请求报文的封装
// response 是对响应报文的封装
app.get('/', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
// 向客户端发送数据
response.send('Hello AJAX')
})
app.post('/', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
// 向客户端发送数据
response.send('Hello AJAX POST')
})
// 启动服务器进行监听
// 8000 端口 服务端在8000端口监听客户端向8000端口发送过来的请求
app.listen(8000, () => {
console.log('服务端在8000端口监听')
})
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Documenttitle>
<style>
#result {
width: 200px;
height: 100px;
border: solid 1px #90b;
}
style>
head>
<body>
<button>发送POST请求button>
<div id="result">div>
<script>
// 获取按钮
const btn = document.querySelector('button')
// 获取div
const div = document.querySelector('div')
// 绑定事件
btn.addEventListener('click', function () {
// 创建发送AJAX请求的对象
const xhr = new XMLHttpRequest()
// 初始化 设置请求的方法和url
xhr.open('POST', 'http://127.0.0.1:8000/')
// 发送请求
xhr.send()
// 处理返回的数据
xhr.onreadystatechange = function () {
// 服务端返回了所有的结果
if (xhr.readyState === 4) {
// 响应状态码 2xx 为成功
if (xhr.status >= 200 && xhr.status < 300) {
// 设置div中的文本
div.innerHTML = xhr.response
}
}
}
})
script>
body>
html>
在xhr.send()中设置,可以设置任意类型任意格式的数据
// 绑定事件
btn.addEventListener('click', function () {
// 创建发送AJAX请求的对象
const xhr = new XMLHttpRequest()
// 初始化 设置请求的方法和url
xhr.open('POST', 'http://127.0.0.1:8000/')
// 发送请求
xhr.send('name=zs&age=12')
...
})
在open方法后进行添加 xhr.setRequestHeader()进行设置
// 绑定事件
btn.addEventListener('click', function () {
// 创建发送AJAX请求的对象
const xhr = new XMLHttpRequest()
// 初始化 设置请求的方法和url
xhr.open('POST', 'http://127.0.0.1:8000/')
//设置请求头
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
// 发送请求
xhr.send('name=zs&age=12')
...
})
// 导入express
const express = require('express')
// 创建应用对象
const app = express()
// 创建路由对象
// request 是对请求报文的封装
// response 是对响应报文的封装
app.get('/', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
// 向客户端发送数据
response.send('Hello AJAX')
})
app.post('/', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
// 向客户端发送数据
response.send('Hello AJAX POST')
})
app.get('/json', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
const data = {
name: 'zs',
age: 12
}
// 对对象进行字符串转换
let str = JSON.stringify(data)
// 向客户端发送数据
response.send(str)
})
// 启动服务器进行监听
// 8000 端口 服务端在8000端口监听客户端向8000端口发送过来的请求
app.listen(8000, () => {
console.log('服务端在8000端口监听')
})
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Documenttitle>
<style>
#result {
width: 200px;
height: 100px;
border: solid 1px #90b;
}
style>
head>
<body>
<button>发送GET请求JSON数据button>
<div id="result">div>
<script>
// 获取按钮
const btn = document.querySelector('button')
// 获取div
const div = document.querySelector('div')
// 绑定事件
btn.addEventListener('click', function () {
// 创建发送AJAX请求的对象
const xhr = new XMLHttpRequest()
// 初始化 设置请求的方法和url
xhr.open('GET', 'http://127.0.0.1:8000/json')
// 发送请求
xhr.send()
// 处理返回的数据
xhr.onreadystatechange = function () {
// 服务端返回了所有的结果
if (xhr.readyState === 4) {
// 响应状态码 2xx 为成功
if (xhr.status >= 200 && xhr.status < 300) {
// 设置div中的文本
div.innerHTML = xhr.response
console.log(xhr.response)
// 手动对数据进行转化
console.log(JSON.parse(xhr.response))
}
}
}
})
script>
body>
html>
设置:
// 设置响应体数据的类型
xhr.responseType = 'json'
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Documenttitle>
<style>
#result {
width: 200px;
height: 100px;
border: solid 1px #90b;
}
style>
head>
<body>
<button>发送GET请求JSON数据button>
<div id="result">div>
<script>
// 获取按钮
const btn = document.querySelector('button')
// 获取div
const div = document.querySelector('div')
// 绑定事件
btn.addEventListener('click', function () {
// 创建发送AJAX请求的对象
const xhr = new XMLHttpRequest()
// 设置响应体数据的类型
xhr.responseType = 'json'
// 初始化 设置请求的方法和url
xhr.open('GET', 'http://127.0.0.1:8000/json')
// 发送请求
xhr.send()
// 处理返回的数据
xhr.onreadystatechange = function () {
// 服务端返回了所有的结果
if (xhr.readyState === 4) {
// 响应状态码 2xx 为成功
if (xhr.status >= 200 && xhr.status < 300) {
// 设置div中的文本
div.innerHTML = xhr.response
console.log(xhr.response)
// 手动对数据进行转化
// console.log(JSON.parse(xhr.response))
}
}
}
})
script>
body>
html>
【Express】
在一些浏览器中(IE),由于缓存机制的存在,ajax 只会发送的第一次请求,剩 余多次请求不会在发送给浏览器而是直接加载缓存中的数据。
解决方式:
浏览器的缓存是根据 url 地址来记录的,所以我们只需要修改 url 地址 即可避免缓存问题。
在请求url后添加?t='+Date.now()
将原来的请求地址:
xhr.open( 'GET', 'http://127.0.0.1:8000/ie' )
修改为:
xhr.open("GET",'http://127.0.0.1:8000/ie?t='+Date.now());
由于每次的请求时间不一样,产生的时间戳不一样,所以每次发起的请求url都不同。
<body>
<button>点击发送请求button>
<div id="result">div>
<script>
const btn = document.getElementsByTagName('button')[0];
const result = document.querySelector('#result');
btn.addEventListener('click', function(){
const xhr = new XMLHttpRequest();
xhr.open("GET",'http://127.0.0.1:8000/ie?t='+Date.now());
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status< 300){
result.innerHTML = xhr.response;
}
}
}
})
script>
body>
请求超时设置:
//超时设置 2s,当请求的时间超过两秒时视为网络请求超时
xhr.timeout = 2000;
//超时回调,当请求超时时要执行的代码
xhr.ontimeout = function(){
alert("网络异常, 请稍后重试!!");
}
服务端代码:
app.get('/delay', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
setTimeout(() => {
// 向客户端发送数据
response.send("HELLO AJAX")
}, 3000)
})
页面:
<style>
#result {
width: 200px;
height: 100px;
border: solid 1px #90b;
}
style>
<body>
<button>点击发送请求button>
<div id="result">div>
<script>
const btn = document.getElementsByTagName('button')[0]
const result = document.querySelector('#result')
btn.addEventListener('click', function () {
const xhr = new XMLHttpRequest()
xhr.timeout = 2000 // 请求时间超过两秒时则为超时
xhr.ontimeout = function(){
console.log('请求超时....')
}
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>
body>
网络异常设置:
//网络异常回调,当网络异常时执行下面的回调
xhr.onerror = function(){
alert("你的网络似乎出了一些问题!");
}
服务端代码:
app.get('/error', (request, response) => {
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
setTimeout(() => {
// 向客户端发送数据
response.send("HELLO AJAX")
}, 3000)
})
网页:
<style>
#result {
width: 200px;
height: 100px;
border: solid 1px #90b;
}
style>
<body>
<button>点击发送请求button>
<div id="result">div>
<script>
const btn = document.getElementsByTagName('button')[0]
const result = document.querySelector('#result')
btn.addEventListener('click', function () {
const xhr = new XMLHttpRequest()
xhr.onerror = function(){
console.log('网络出现了问题.....')
}
xhr.open( 'GET', 'http://127.0.0.1:8000/error' )
xhr.send()
xhr.onreadystatechange = function() {
if ( xhr.readyState===4 ) {
if ( xhr.status>=200 && xhr.status<300 ) {
result.innerHTML = xhr.response
}
}
}
})
script>
body>
使用 abort() 方法放弃请求
<body>
<button>点击发送button>
<button>点击取消button>
<script>
const btns = document.querySelectorAll('button')
const xhr = new XMLHttpRequest()
btns[0].onclick = function() {
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 ) {
console.log(xhr.response)
}
}
}
}
btns[1].onclick = function() {
xhr.abort()
}
script>
body>
重复频繁的发送同一个请求会对服务端照常压力。
当前已经发送了请求,再次发送请求时,取消前一次的请求。
<body>
<button>点击发送button>
<script>
//获取元素对象
const btn = document.querySelector('button')
let xhr = null
// 设置一个标识,是否正在发送请求
let isSending = false
btn.onclick = function () {
// 如果正在发送请求,取消前面的请求
if( isSending ) xhr.abort()
xhr = new XMLHttpRequest()
isSending = true // 正在发送请求
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) {
// 请求回来后
isSending = false
console.log(xhr.response)
}
}
}
}
script>
body>
【AJAX中文文档】
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Documenttitle>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js">script>
head>
<body>
<button>发送GETbutton>
<button>发送POSTbutton>
<button>通用方法发送请求button>
<script>
// eq()选择第几个元素
$('button')
.eq(0)
.click(function () {
// 第一个参数,请求的地址
// 第二个参数,请求携带的参数
// 第三个参数,请求回来的回调函数
$.get('http://127.0.0.1:8000', { a: 100, b: 200 }, function (data) {
console.log(data)
})
})
$('button')
.eq(1)
.click(function () {
// 第一个参数,请求的地址
// 第二个参数,请求携带的参数
// 第三个参数,请求回来的回调函数
$.post('http://127.0.0.1:8000', { a: 100, b: 200 }, function (data) {
console.log(data)
})
})
$('button').eq(2).click(function(){
// 参数为一个对象
$.ajax({
// 请求的url
url: 'http://127.0.0.1:8000/json',
// 请求携带的参数
data: {a: 100, b: 200},
// 请求的方式
type: 'GET',
// 设置响应体的数据形式
dataType: 'json',
// 设置成功的回调函数
success: function(data) {
console.log(data)
},
// 设置超时时间
// 超时会执行error的回调
timeout: 2000,
// 失败的回调
error: function() {
console.log('ERROR')
},
// 设置请求的头信息
// headers: {
// c: 300,
// d: 400
// }
})
})
script>
body>
html>
【axios github仓库地址】
在后端服务器设置了跨域,在前端页面依旧显示跨域问题,在前端请求中设置请求头:
//请求头参数
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
因为大多数服务器只能识别请求头 Content-Type 为 application/x-www-form-urlencodedaxios 的请求,而 axios 的 Content-Type 是 application/json
【解决方法博客】
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Documenttitle>
<script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/axios/0.19.2/axios.js">script>
<script src="https://cdn.bootcss.com/qs/6.9.0/qs.min.js">script>
head>
<body>
<button>GETbutton>
<button>POSTbutton>
<button>AJAXbutton>
<script>
const btns = document.querySelectorAll('button')
//配置 baseURL
axios.defaults.baseURL = 'http://127.0.0.1:8000'
btns[0].onclick = function () {
// 返回的为promise对象
// 第一个参数为请求地址
// 第二个参数为配置信息
axios
.get('/', {
// 参数
params: {
name: 'zs',
age: 12,
},
//请求头参数
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
})
.then((response) => {
console.log(response)
})
}
btns[1].onclick = function () {
// 第一个参数请求地址
// 第二个参数为请求携带参数
// 第三个参数为配置信息
axios
.post(
'/',
{
name: 'zs',
age: 12,
},
{
params: {
a: 100,
b: 200,
},
//请求头参数
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
}
)
.then((response) => {
console.log(response)
})
}
btns[2].onclick = function () {
axios({
//请求方法
method: 'POST',
//url
url: '/',
//url参数
params: {
vip: 10,
level: 30,
},
//头信息
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
//请求体参数
data: {
username: 'admin',
password: 'admin',
},
}).then((response) => {
//响应状态码
console.log(response.status)
//响应状态字符串
console.log(response.statusText)
//响应头信息
console.log(response.headers)
//响应体
console.log(response.data)
})
}
script>
body>
html>
【文档地址】
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Documenttitle>
head>
<body>
<button>AJAX请求button>
<script>
//文档地址
//https://developer.mozilla.org/zh-CN/docs/Web/API/WindowOrWorkerGlobalScope/fetch
const btn = document.querySelector('button')
btn.onclick = function () {
fetch('http://127.0.0.1:8000/', {
//请求方法
method: 'POST',
//请求头
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
//请求体
body: 'username=admin&password=admin',
})
.then((response) => {
return response.text()
// return response.json()
})
.then((response) => {
console.log(response)
})
}
script>
body>
html>
【文档】
CORS(Cross-Origin Resource Sharing),跨域资源共享。CORS 是官方的跨域解决方案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持 get 和 post 请求。跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些 源站通过浏览器有权限访问哪些资源
CORS 是通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应 以后就会对响应放行。
主要是服务器端的设置:
// 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*');
// 设置响应头
response.setHeader('Access-Control-Allow-Headers', '*');
// 设置允许请求的方法
response.setHeader('Access-Control-Allow-Methods', '*');
...
在后端服务器设置了跨域,在前端页面依旧显示跨域问题,在前端请求中设置请求头:
//请求头参数
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
因为大多数服务器只能识别请求头 Content-Type 为 application/x-www-form-urlencodedaxios 的请求,而 有的请求的 Content-Type 是 application/json
【解决方法博客】
轻松搞定JSONP跨域请求 – 诗渊
【https://blog.csdn.net/u014607184/article/details/52027879】