注意AJAX的步骤
javascript
// 1.创建对象
const xhr = new XMLHttpRequest()
// 2.初始化 设置 请求方法 和 url
xhr.open("GET", "http://localhost:9090/server")
// 3.发送
xhr.send()
// 4.事件绑定 处理服务端返回的结果
// readyState 是xhr对象中的属性,表示状态 0 1 2 3 4
// 0 表示初始值; 1 表示open()方法调用完毕;2 表示send()方法调用完毕;3 表示服务端返回了部分结果;4 表示服务端返回了所有的结果
// change 改变
xhr.onreadystatechange = function () {
// 判断状态码
if (xhr.readyState === 4) {
// 判断状态码
if (xhr.status >= 200 && xhr.status < 300) {
// 获取服务端返回的结果 (行 头 空行 响应体)
console.log(xhr.status) // 响应行里面的响应状态码 200
console.log(xhr.statusText) // 状态字符串 OK
console.log(xhr.getAllResponseHeaders()) // 所有响应头
console.log(xhr.response) // 响应体
const result = xhr.response
}
}
}
1. GET 请求
需求:向服务端发送get请求,拿到服务端返回的结果,并显示在div盒子中
(1)server.js
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 GET')
})
// 4. 监听端口
app.listen(9090, () => {
console.log("服务已启动, 9090端口监听中...")
})
(2)前端页面并渲染服务端返回的结果
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ajax GET 请求</title>
<style>
#result {
width: 200px;
height: 100px;
border: 1px solid pink;
}
</style>
</head>
<body>
<button id="btn">点击发送请求</button>
<div id="result">
</div>
<script>
// 获取button元素
const btn = document.querySelector("#btn")
// 绑定事件
btn.addEventListener("click", function () {
// console.log("test")
// 1.创建对象
const xhr = new XMLHttpRequest()
// 2.初始化 设置请求方法和url
xhr.open("GET", "http://localhost:9090/server?a=100&b=30") // 携带参数
// 3.发送
xhr.send()
// 4.事件绑定 处理服务端返回的结果
// readyState 是xhr对象中的属性,表示状态 0 1 2 3 4
// change 改变
xhr.onreadystatechange = function () {
// 判断状态码
if (xhr.readyState === 4) {
// 判断状态码
if (xhr.status >= 200 && xhr.status < 300) {
// 获取服务端返回的结果 (行 头 空行 响应体)
console.log(xhr.status) // 响应行里面的响应状态码 200
console.log(xhr.statusText) // 状态字符串 OK
console.log(xhr.getAllResponseHeaders()) // 所有响应头
console.log(xhr.response)
const result = xhr.response // 响应体
// 把结果放到div中
document.querySelector("#result").innerHTML = result
}
}
}
})
</script>
</body>
</html>


2. GET请求携带参数


3. POST请求
当鼠标放在div盒子上时,向服务端发送post请求,将响应的结果在div中呈现
(1)server.js
javascript
// 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 POST')
})
// 4. 监听端口
app.listen(9090, () => {
console.log("服务已启动, 9090端口监听中...")
})
(2)前端页面并渲染数据到盒子中
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ajax POST 请求</title>
<style>
#result {
width: 200px;
height: 100px;
border: 1px solid pink;
}
</style>
</head>
<body>
<div id="result">
</div>
<script>
// 获取元素对象
const result = document.querySelector('#result')
// 绑定事件
result.addEventListener('mouseover', function (){
// console.log('鼠标移动')
// 1. 创建对象
const xhr = new XMLHttpRequest()
// 2. 初始化 设置类型与URL
xhr.open('POST', 'http://localhost:9090/server')
// 3. 发送
xhr.send()
// 4. 事件绑定
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
// 获取服务器响应的数据
const data = xhr.responseText
// 把数据渲染到页面
result.innerHTML = data
}
}
}
})
</script>
</body>
</html>

4. POST请求中设置参数


5. AJAX设置请求头信息


但是如果自定义一个请求头呢,浏览器会有安全机制,不让发送

如果我们非要发的话,可以用以下的方法


6. 服务端响应JSON数据
需求:当点击键盘时,会向服务端发送请求,服务端响应结果会在div盒子中呈现

html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#result {
width: 200px;
height: 100px;
border: 1px solid pink;
}
</style>
</head>
<body>
<div id="result">
</div>
<script>
// 获取元素对象
const result = document.querySelector('#result')
window.onkeydown = function(e){
// console.log(e.key, e.keyCode)
// 1. 发送请求
const xhr = new XMLHttpRequest()
// 设置响应体类型
// xhr.responseType = 'json' // 可以自动转换
// 2. 初始化 设置请求方法和url
xhr.open('GET', 'http://localhost:9090/server_json')
// 3. 发送
xhr.send()
// 4.事件绑定
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
// 获取服务器响应的数据
const data = xhr.response
result.innerHTML = data
console.log(data)
}
}
}
}
</script>
</body>
</html>

1. 手动转换


2.自动转换

7. AJAX解决IE缓存问题
IE浏览器会对请求结果作一个缓存,这样就会导致一个问题,就是下一次再发送请求时,走的就是本地的缓存,而并不是服务器返回的最新数据
javascript
/* 针对IE缓存问题 */
app.all('/ie', (request, response) => {
// 设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*')
// 响应头
response.setHeader('Access-Control-Allow-Headers', '*') // 所有类型的头信息都可以接受
// 设置响应体
response.send("hello IE")
})
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#result {
width: 200px;
height: 100px;
border: 1px solid pink;
}
</style>
</head>
<body>
<button>点击发送请求</button>
<div id="result">
</div>
<script>
// 获取元素
const btn = document.getElementsByTagName('button')[0]
const result = document.getElementById('result')
btn.addEventListener("click", function() {
const xhr = new XMLHttpRequest()
xhr.open('GET', 'http://localhost:9090/ie?t='+Date.now()) // 加个参数解决IE缓存问题
xhr.send();
xhr.onreadystatechange = function() {
if(xhr.readyState === 4) {
if(xhr.status >= 200 && xhr.status < 300) {
// 处理服务端返回的结果
result.innerHTML = xhr.response;
}
}
}
})
</script>
</body>
</html>

8. AJAX请求超时以及网络异常处理
1.请求超时

html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#result {
width: 200px;
height: 100px;
border: 1px solid pink;
}
</style>
</head>
<body>
<button>点击发送请求</button>
<div id="result">
</div>
<script>
// 获取元素
const btn = document.getElementsByTagName('button')[0]
const result = document.getElementById('result')
btn.addEventListener("click", function() {
const xhr = new XMLHttpRequest()
// 超时设置
xhr.timeout = 2000
// 超时回调
xhr.ontimeout = function() {
alert('网络异常,请稍后重试!')
}
xhr.open('GET', 'http://localhost:9090/delay')
xhr.send()
xhr.onreadystatechange = function() {
if(xhr.readyState === 4) {
if(xhr.status >= 200 && xhr.status < 300) {
// 处理服务端返回的结果
result.innerHTML = xhr.response;
}
}
}
})
</script>
</body>
</html>


2. 网络异常

9. AJAX取消请求


10. AJAX解决请求重复发送问题
当请求响应比较慢的时候,用户就会疯狂地点击,这时候服务器就会接收到大量的相同请求,服务器压力比较大
所以我们需要保证始终只有一个请求在发送,这样服务器的压力就会小一些



11. jQuery发送AJAX请求
首先需要引入jQuery资源
11.1 发送GET请求
javascript
app.get('/jquery', (request, response) => {
// 设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*')
// 响应头
response.setHeader('Access-Control-Allow-Headers', '*') // 所有类型的头信息都可以接受
response.send("hello jQuery AJAX")
})
javascript
$("#btn1").click(function() {
// 第一个参数是url, 第二个参数是发送的参数(对象的形式), 第三个参数是回调函数
$.get("http://localhost:9090/jquery", {a:100, b:200}, function(data, status) {
console.log(data)
})
})

11.2 发送POST请求
javascript
app.post('/jquery', (request, response) => {
// 设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*')
// 响应头
response.setHeader('Access-Control-Allow-Headers', '*') // 所有类型的头信息都可以接受
response.send("hello jQuery AJAX POST")
})
javascript
$("#btn2").click(function() {
$.post("http://localhost:9090/jquery", {a:100, b:200}, function(data, status) {
console.log(data)
})
})
POST请求携带的参数不会跟在url后面

11.3 设置响应体的数据类型
javascript
/* jQuery服务 */
app.all('/jquery', (request, response) => {
// 设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*')
// 响应头
response.setHeader('Access-Control-Allow-Headers', '*') // 所有类型的头信息都可以接受
const data = {name: "xiexu", age: 20}
response.send(JSON.stringify(data))
})
服务端发送json格式的数据


11.4 jQuery通用方法发送AJAX请求



12. Axios发送AJAX请求
首先需要引入axios工具包
12.1 发送GET请求
javascript
app.get('/axios', (request, response) => {
// 设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*')
// 响应头
response.setHeader('Access-Control-Allow-Headers', '*') // 所有类型的头信息都可以接受
response.send("hello Axios AJAX")
})

获取的数据是比较完整的

12.2 发送POST请求

javascript
/* axios 服务*/
app.all('/axios', (request, response) => {
// 设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*')
// 响应头
response.setHeader('Access-Control-Allow-Headers', '*') // 所有类型的头信息都可以接受
response.send("hello Axios AJAX POST")
})

12.3 Axios通用方式发送AJAX请求


13. fetch() 函数发送AJAX请求
javascript
/* fetch */
app.all('/fetch', (request, response) => {
// 设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*')
// 响应头
response.setHeader('Access-Control-Allow-Headers', '*') // 所有类型的头信息都可以接受
const data = {name: "x666", age: 20}
// response.send("hello jQuery AJAX")
response.send(JSON.stringify(data))
})


14. 解决跨域问题
同源策略是最早由Netscape公司提出,是浏览器的一种安全策略
同源:协议、域名、端口号必须相同; 违背同源策略就是跨域
解决跨域的方法:
14.1 JSONP
JSONP是一个非官方的跨域解决方案,只支持get请求
(1)JSONP是怎么工作的?
在网页中,由一些标签天生具有跨域的能力,比如img、link、iframe、script,JSONP就是利用script标签的跨域能力来发送请求的
(2)JSONP实现原理
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>jsonp解决跨域问题</title>
</head>
<body>
<script src="http://localhost:9090/jsonp">
</script>
</body>
</html>
javascript
app.all('/jsonp', (request, response) => {
response.send("hello jsonp")
})

这个原因就是我正儿八经的script标签向你发送请求,你却返回一个字符串的形式,我们应该返回的是函数的调用,也就是js的代码,这样浏览器才能执行里面的内容


14.2 原生JSONP的实现
**需求:**有一个输入框,在里面输入用户名,输完之后,我会失去焦点,失去焦点的时候,就会向服务端发送请求,对用户名是否存在的检测,因为这边没有数据库,所以服务端直接返回一个已存在,结果回来之后了,我们作一个判断,再把input框的颜色变为红色
javascript
/* 用户名检测是否存在 */
app.all('/checkUserName', (request, response) => {
const data = {
exists: 1,
msg: "用户名已存在"
}
let str = JSON.stringify(data)
response.send(`handle(${str})`)
})


14.3 jQuery发送JSONP请求
需求:点击按钮,向服务端发送请求,响应的结果再div盒子中呈现



14.4 设置CORS响应头实现跨域
(1)CORS是什么?
CORS(Cross-Origin Resource Sharing), 跨域资源共享。CORS是官方的跨域解决方案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持get和post请求。跨域资源共享标准新增了一组HTTP首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源。
(2)CORS是怎么工作的?CORS通过设置一个响应头告诉浏览器,请允许跨域,浏览器收到该响应以后就会对响应放行



修改:添加响应头

成功响应:
