AjAx 的特点
优点
- 可以无需刷新页面与服务器进行通信
- 允许你根据用户事件来更新部分页面内容
缺点
- 没有浏览历史 不能回退
- 存在跨域问题(同源)
- SEO 不友好
请求报文
重点是格式和参数
-
请求体
-
响应体
-
gei 请求 参数
-
post 请求体参数
Ajax的使用
// 创建对象
const xhr = new XMLHttpRequest()
// 初始化 设置请求方法和 url
xhr.open("GET","http://127.0.0.1:8000/serve")
// 发送
xhr.send()
// 事件绑定 处理服务器返回的结果
// on when 当。。。 时候
// readystate 是 xhr 对象中的属性 表示状态 0 1 2 3 4
// 0 对象初始化完成 1 open 完成 2 send 完成 3 请求数据部分 返回 4 请求数据全部返回
xhr.onreadystatechange = function(res){
// 满足下列条件 请求数据成功
if(xhr.readyState == 4 && (xhr.status >= 200 && xhr <300)){
// status 响应状态码 =》 200 300 400 500
// 2 开头都是表示成功
let data = xhr.response // 响应体的内容
}else {
}
}
Ajax设置参数
- get 请求设置参数
xhr.open("GET","http://127.0.0.1:8000/serve?a=100&b=200&c=300")
- post 设置请求参数
// & 分隔
xhr.send("a=100&b=200&c=300")
// 冒号分隔
xhr.send("a=100:b=200:c=300")
设置请求头
在请求中(如POST 或 PUT) content-Type字段用于客户端告诉服务器实际发送的数据类型 方便服务器去解析数据 如果你不管服务器无法理解你的请求
- content-Type 用来设置请求参数类型的
注意 在 open 和 send 之间 设置
// 设置请求头 接受两个参数
xhr.setRequestHeader("content-Type",'application/x-wwww-form-urlencoded')
- 自定义请求头 属性 报错 (浏览器不允许)如果硬要这么做 需要在后台设置
// 对所有请求进行处理
app.use((req, res, next) => {
//设置请求头
res.set({
'Access-Control-Allow-Headers': 'X-Requested-With,Content-Type',
'Access-Control-Allow-Headers': '*',
})
// 对特定的路由处理
app.get('/api/wx/getSignature.do', (req, res) => {
res.set({
'Access-Control-Allow-Headers': 'X-Requested-With,Content-Type',
'Access-Control-Allow-Headers': '*',
})
}
后台设置还不行 还会再次校验 发送一个option 请求 校验这个头信息是否可用
app.get('/api/wx/getSignature.do', (req, res) => {
}
- 此时这个请求路由类型要改为 all 校验 是发的 option
app.all('/api/wx/getSignature.do', (req, res) => {
}
服务器响应JSON数据
- 方式一、
// 后台返回数据
app.get('/api/wx/getSignature.do', (req, res) => {
let obj = {a:1,b:2}
let str = JSON.stringify(obj)
res.send(str)
}
//前端接收时
JSON.parse(xhr.rsponse)
- 方式二、
// 设置响应数据的类型
xhr.responseType = "json"
Ajax IE 缓存问题
- IE GET请求 是有缓存 对于该接口展示数据有一定的时效性 第二次请求 是会走缓存 不会再次请求
// 让每次发的请求的url都不一样
xhr.open("GET",`http://127.0.0.1:8000/IE?t=${Date.now()}`)
Ajax 请求超时
- 设置 超时 回调函数 增加用户体验
const xhr = new XMLHttpRequest()
// 如果 两秒钟后客户端还没有返回 就取消请求
xhr.timeout = 2000
// 请求超时 回调函数
xhr.ontimeout = function(){
alert('请求超时')
}
// 网络异常处理函数
xhr.onerror = function(){
alert('网络异常')
}
xhr.open( "GET","/delay")
xhr.send()
xhr.onreadystatechange = function(res){
if(xhr.readyState==4 && xhr.status >= 200 && xhr <300){
}
}
// --------------------------------->
// 解决跨域
app.use((req, res, next) => {
//设置请求头
res.set({
'Access-Control-Allow-Credentials': true,
'Access-Control-Max-Age': 1728000,
'Access-Control-Allow-Origin': req.headers.origin || '*',
'Access-Control-Allow-Headers': 'X-Requested-With,Content-Type',
'Access-Control-Allow-Methods': 'PUT,POST,GET,DELETE,OPTIONS',
'Content-Type': 'application/json; charset=utf-8'
})
next()
})
app.get('/delay', (req, res) => {
}
Ajax取消请求
- 当我们发送ajax请求 但是请求没有返回结果 我们可以手动取消请求 (跟请求超时类似 超时未返回 自动取消)
// xhr 与发送的请求的 xhr 必须是同一个实例
xhr.abort()
解决Ajax 重复发送请求
- 方式一、
let btn = document.querySelector('.btn')
let xhr = null;
let isok = false;
btn.conclick() = function () {
if(isok) xhr.abort() // 正在发送请求
xhr = new XMLHttpRequest() // 创建一个请求
isok = true
xhr.open("GET", "/delay")
xhr.send()
xhr.onreadystatechange = function (res) {
if (xhr.readyState == 4 && xhr.status >= 200 && xhr < 300) {
isok = false
}
}
}
- 方法二 防抖和节流
jQuery 请求 Ajax
- 引入 在线 jquery 会有这个提示 在 scrip 标签加
// crossorigin="anonymous" 表示这个资源发送请求 不会发送当前域名下的cooki
<script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
- get
$.get('http//dadas/..',{a:1,b:2},function(res){
},'json') // 表示返回的数据格式是 json类型
- post
$.post('http//dadas/..',{a:1,b:2},function(res){
},'json') // 表示返回的数据格式是 json类型
- 通用的请求
//后台
app.all('/api/wx/getSignature.do', (req, res) => {
let data ={
a:1,
b:2
}
let str = JSON.stringify(data)
res.send(str)
}
$.ajax({
type: "GET",
url: "test.js",
dataType:'json' // 这一步 相当于 把 JSON。parse(data)
timeout: 3000, // 超时时间
header:{ //请求头信息的设置
a: 1,
b:2
},
// 失败的回调
error:()=>{
},
success:(data)=>{
}
});
axios 发送Ajax 请求
<script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.js"></script>
// 全局默认配置
axios.defaults.baseURL = 'https://api.example.com';
// 发送 POST 请求
axios({
method: 'post',
url: '/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
}).then((res)=>{
})
fetch 发送Ajax 请求
fetch('http://example.com/movies.json')
.then(function(response) {
return response.json();
})
.then(function(myJson) {
console.log(myJson);
});
feth 设置请求头
使用 fetch 提供的 API 即可设置
let myheader = new Headers()
myheader.append("content-Type","application/json")
原生JSONP如何解决跨域
jsonp是一个非官方的跨域解决方案 只支持 get请求
- jsonp 的原理 在网页中有一些标签天生具有跨域的能力 比如 ing link iframe scrip src属性 jsonp 就是利用script 标签的跨域 能力来发送请求的
- jsonp 使用
1、动态的创建一个 script 标签 并定义全局的函数
// 全局函数
<script >
function handle(data){
console.log('我被调用了',data)
}
</script>
var script = document.createElemnt('script')
2、设置 script 的 src 设置回调函数
// ?callback=? 固定写法 jQuery 中 jsonp
script.src = 'https:/api/wx/getSignature.do?callback=?'
3.插入页面中
document.body.appendChild(script) //
- 后台的设置
app.get('/api/wx/getSignature.do', (req, res) => {
let obj= "我是后台传过来的"
res.send(` handle(${obj})`) // 返回后回调用客户端全局函数 handle
}
query 中的jsonp
- 和原生的jsonp 区别是 不用设置全局函数 需要后端配合拿到 callback 值 并传递前端所需要的数据
JSONP形式的回调函数来加载其他网域的JSON数据,如 “myurl?callback=?”。jQuery 将自动替换 ?
为正确的函数名,
// 后台
app.get('/api/wx/getSignature.do', (req, res) => {
let cb = req.query.callback // 拿到函数名
let obj= {
name:"尚硅谷",
city:["北京","上海","深圳"]
}
res.send(`${cb}(${obj})`) // 返回后回调用客户端全局函数 handle
}
// ------------------------------>
jQuery.getJSON(url, [data], [callback])
$.getJSON({
'http://dadadad/ada?callback=?',
function(res) {
consol.log(res)
/*obj= {
name:"尚硅谷",
city:["北京","上海","深圳"]
}
*/
}
})
- 后台需要把该参数接手到 传递参数 再次传给客户端