Ajax
AJAX简介
全称:Asynchronous JavaScript And XML,异步的JS和XML
通过AJAX可以在浏览器中向服务器发送异步请求,无需刷新就能获取数据
能在页面不刷新的情况下向http发送请求,得到http响应
应用场景
-
页面上拉加载更多数据
-
列表数据无刷新分布
-
表单项离开焦点时数据验证
-
搜索框提示文字下拉列表
AJAX的特点
AJAX的优点
-
无需刷新页面而与服务器进行通信
-
允许根据用户事件来更新部分页面内容
AJAX的缺点
-
没有浏览历史,不能回退
-
存在跨域问题(同源)
-
SEO不友好
HTTP
HTTP(hypertext transport protocol)超文本传输协议,详细规定了浏览器和万维网服务器之间互相通信的规则,主要用来规范客户端的请求报文与服务端报文的响应
-
请求报文包含以下内容(发送请求时)
-
行:请求类型(get/post/put..)+url路径(如:/video/BV1WC4y1b78y)+http版本
-
头:Host+Cookie+Content-type 等,请求头可有可无。如:
Host:baidu.com Cookie:name=baidu content-type:application/x-www-form-urlencoded//请求的类型 User-Agent:chrome
-
空行:固定格式必须有
-
体:可有可无,如:请求类型为get时为空,post时可为空可不为空
username=admin&password=123456
-
-
响应报文包含以下内容 行+头
-
行:http协议版本+响应状态码+响应字符串
HTTP状态码 1XX:消息响应,服务器收到请求,需要请求者继续执行操作 2xx:成功响应,操作被成功接收并处理 3xx:重定向响应,需要进一步的操作以完成请求 4xx:客户端错误,请求包含语法错误或无法完成请求 5xx:服务器端错误,服务器在处理请求的过程中发生了错误 常见状态码 200:请求成功,用于get和post请求 301:永久移动,资源被永久转移到其它URL,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替 404:请求资源不存在,找不到 500:内部服务器错误,无法完成请求 其他状态码 100:继续,客户端应继续其请求 101:切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议 201:已创建。成功请求并创建了新资源 202:已接受。已接受请求,但未处理完成 203:非授权信息。请求成功,但返回的meta信息不在原始的服务器,而是一个副本 204:无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档 205:重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域 206:部分内容。服务器成功处理了部分GET请求 300:多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择 302:临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI 303:查看其它地址。与301类似。使用GET和POST请求查看 304:未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源 305:使用代理。所请求的资源必须通过代理访问 306:已经被废弃的HTTP状态码 307:临时重定向。与302类似。使用GET请求重定向 400:客户端请求的语法错误,服务器无法理解 401:请求要求用户的身份认证(未授权) 402:保留,将来使用 403:服务器理解请求客户端的请求,但是拒绝执行此请求 405:客户端请求中的方法被禁止 406:服务器无法根据客户端请求的内容特性完成请求 407:请求要求代理的身份认证,与401类似,但请求者应当使用代理进行授权 408:服务器等待客户端发送的请求时间过长,超时 409:服务器完成客户端的 PUT 请求时可能返回此代码,服务器处理请求时发生了冲突 410 :客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置 411:服务器无法处理客户端发送的不带Content-Length的请求信息 412:客户端请求信息的先决条件错误 413:由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个Retry-After的响应信息 414:请求的URI过长(URI通常为网址),服务器无法处理 415:服务器无法处理请求附带的媒体格式 416:客户端请求的范围无效 417:服务器无法满足Expect的请求头信息 501:服务器不支持请求的功能,无法完成请求 502:作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应 503:由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中 504:充当网关或代理的服务器,未及时从远端服务器获取请求 505:服务器不支持请求的HTTP协议的版本,无法完成处理
-
-
头(格式与请求报文头一样)
content-type:text/html;charset=utf-8//格式 content-length:2048//长度 content-encoding:gzip//压缩方式
-
空行
-
体:响应体。拿到的内容如html文件,浏览器会对其进行解析并显示
AJAX初始
AJAX的GET请求
需求:点击按钮向服务器发送请求
客户端
//客户端
//获取button元素
var btn=document.getElementById('btn')
//绑定事件
btn.onclick=function(){
//创建AJAX对象
const xhr=new XMLHttpRequest()
//初始化,设置请求方法和url
xhr.open('GET', "http://127.0.0.1:3000/service")
//设置请求头,身份校验的信息在此处,
//将信息传递给服务器后服务器会对参数进行提取并对身份进行校验
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
//发送
xhr.send()
//事件绑定处理服务端返回的结果
//onreadystatechange当状态改变时触发共有5个状态0未初始化,1open方法调用完毕,2send方法调用完毕,3服务端返回了部分结果,4表示结果全部返回
xhr.onreadystatechange = function () {
//服务端返回了所有的结果才处理
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300)//2开头都为成功
{//处理结果 行 头 空行 体
//响应行
console.log(xhr.status)//状态码
console.log(xhr.statusText)//状态字符串
console.log(xhr.getAllResponseHeaders())//所有响应头
console.log(xhr.response)//响应体
result.innerHTML = xhr.response
}
}
}
}
服务端
//服务端
//引入express
const express=require('express')
//创建应用对象
const app=express()
//创建路由规则
//req是对请求报文的封装
//res是对响应报文的封装
app.get('/server',(req,res)=>{
//设置响应头,允许跨域
res.setHeader('Access-Control-Allow-Origin','*')
//响应头,设置可以传递任何模式的响应头,自定义的也可
res.setHeader('Access-Control-Allow-Headers', '*')
//设置响应体
res.send()
})
//监听端口启动服务
app.listen(8000,()=>{
})
注意:post与get的代码类似,将get改成post即可
AJAX传递参数
-
GET传递参数
在open中的url地址后面以?间隔key=value的形式传递,多个参数之间用&符分隔如:
xhr.open('GET', "http://127.0.0.1:3000/service?name=zs&age=12")
-
POST传递参数
将要传递的参数以key=value&key1=value或key:value&key1=value1的形式写入xhr.send()中去如:
xhr.send(name=zs&age=12)
AJAX如何处理服务器传过来的JSON字符串
因为服务器res.send()里所传的值只能为字符串,因此要将JSON数据转换成字符串,前端需要对字符串进行处理,有以下两种方法:
-
JSON.parse()方法
JSON.parse(xhr.response)
-
通过设置响应体数据类型
xhr.responseType='json'//此方法即可将字符串转成JSON类型 xhr.response//可以得到JSON整体数据 xhr.response.属性名//得到JSON数据中的某一值
IE缓存问题
IE浏览器存在缓存机制,当浏览器请求一次数据后,后端数据再改变浏览器不会及时获得新数据拿到了是缓存中原有的数据。
如何解决
-
在请求地址上加上一个时间戳(或不同的值)如:
xhr.open("GET",'http://127.0.0.1:3000/ie?t='+Date.now())
请求超时与网络异常处理
xhr.timeout=num//超时设置,当请求超过2s后还未获得结果则请求取消
//请求超时处理
xhr.ontimeout=function(){
alert('网络异常,请稍后重试')
}
//网络异常处理
xhr.onerror=function(){
alert('你的网络似乎出了些问题')
}
解决AJAX重复发送请求的问题
let xhr=null
//标识变量,当前是否正在发送AJAX请求
let isSending=false;
btn.onclick=function(){
if(isSending) xhr.abort()//如果正在发送,则取消该请求
//创建新的请求
xhr=new XMLHttpRequest();
//修改标识变量的值
isSending=true;
xhr.open('GET','http://127.0.0.1:3000/delay')
xhr.send()
xhr.onreadystatechange=function(){
//请求发送成功后,说明当前没有请求所以要更改标识变量
if(xhr.readyState===4){
isSending=false//修改标识变量
}
}
}
Jquery发送AJAX请求
方法1.基本语法$.get(请求路径,请求参数,回调函数,参数格式)如:
$.get('http://127.0.0.1:3000/service',{a:100,b:200},function(data){
console.log('hello')
},'json')
//如要发送post请求则将get换成post即可
方法2.基本语法$.ajax({url:请求路径,data:请求参数,type:请求类型,dataType:响应体参数格式,success:成功的回调,timeout:超时时间,error:失败的回调})如 :
$.ajax({
url:'http://127.0.0.1:3000/service',
data:{A:100,B:200},
type:'GET',
dataType:'json'
//成功的回调
success:function(){
console.log('我成功啦')
},
timeout:2000,
error:function(){
console.log('我出错了')
}
})
axios发送AJAX请求
Axios 是一个基于 Promise 的 HTTP 库,可以用在浏览器和 node.js 中。
配置baseURL
axios.defaults.baseURL='http://127.0.0.1:3000'
发送GET请求
//因为已经设置了baseURL所以在此只要写service即可
axios.get('/service',{
//url参数
params:{},
//请求头信息
headers:{}
}).then(val=>{})
发送POST请求
//因为已经设置了baseURL所以在此只要写service即可
axios.post('/service',请求体,{
//url参数
params:{},
//请求头信息
headers:{}
}).then(val=>{})
通用方法
axios({
method:请求方式
url:url参数,
params:url参数,
headers:头信息,
data:请求体参数
}).then(res=>{
res.status//状态码
res.statusText//响应状态字符串
res.headers//响应头信息
res.data//响应体
})
fetch()函数发送AJAX请求
fetch('http://127.0.0.1:3000/service?age=12',{//?后面为请求参数
method:请求方式,
headers:请求头,如:{name:'zs',age:12}
body:请求体,如:'name=zs&age=15'
}).then(res=>{
return res.text()//取响应体
}).then(res=>{
console.log(res)//此处输出的res值为上个then所返回的结果
})
跨域
同源策略
浏览器的一种安全策略,同源指的是http协议、域名、以及端口号完全相同,如果违背同源策略则是跨域。AJAX是满足同源策略的,若不符合则不能发起AJAX请求
如何解决跨域
JSONP
JSONP(JSON with Padding),是一个非官方的跨域解决方案,只支持get请求。因为在网页中有一些标签本来就具有跨域能力(比如:img link iframe script),所以JSONP利用script标签跨域能力来发送请求。
JSONP原理
-
首先利用script标签的src属性来实现跨域
-
通过将前端方法作为参数传递到服务器,然后由服务器加入参数后再返回,以此实现服务器向客户端通信
-
由于使用script标签的src属性,因此只支持get方法
//前端代码展示 <script> function handle(date){ const result=document.getElementById('result') result.innerHTML=data.name } </script> <script src="http://127.0.0.1:3000/service"></script>
//服务端代码展示 app.all('/service',(req,res)=>{ const data={ name:'zs' } let str=JSON.stringify(data) res.end(`handle(${str})`)//会去执行前端代码中的函数 })
JSONP的使用
//前端代码 function handle(data) { user.style.border = "1px solid red" user.value = data } user.onblur = function (data) { var script = document.createElement('script') script.src = "http://127.0.0.1:3000/service" document.body.appendChild(script) }
//后端代码 app.get('/service', (req, res) => { var data = Date.now() var str = JSON.stringify(data) res.end(`handle(${data})`) })
Jquery发送JSONP请求
//前端代码
$('button').eq(0).click(function(){
$.getJSON('http://127.0.0.1:3000/service?callback=?',function(){
//对返回的数据进行处理
$('#result').html(data)
})//url中的callback=?是必填参数
})
//后端代码
app.get('/service', (req, res) => {
var data = Date.now()
var str = JSON.stringify(data)
//接收callback参数
let cb=req.query.callback
//将callback返回
res.end(`${cb}(${str})`)
})
CORS
CORS跨域资源共享,不需要 在客户端做任何特殊操作,完全在服务器中进行处理,支持get和post请求。跨域资源共享标准新增了一组HTTP首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源
CORS怎么工作的?
通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应以后就会对响应放行
CORS的使用
app.post('/service', (req, res) => {
//设置响应头,允许跨域
res.setHeader('Access-Control-Allow-Origin', '*')
res.setHeader('Access-Control-Allow-Headers', '*')
res.setHeader('Access-Control-Allow-Method', '*')
//设置响应体
res.send('hello')
})