- XMLHttpRequest对象是AJAX技术的核心
- 简单来说,AJAX发送并接受响应一共为四步
let xhr = new XMLHttpRequest(); //创建XMLHttpRequest对象实例
xhr.open(); //与服务端建立连接
xhr.send(); //发送请求
xhr.onreadystatechange //处理响应
注:IE中有三种不同的XHR对象,我们这里只谈最常用的,适用于IE7及以上的
原生AJAX发送get请求
- get请求很简单,因为get请求没有请求体,数据都是放置于URL后的,所以我们只需要使用拼串方法即可 注:xhr.open方法中有三个参数(请求方法,拼串后的URL,是否异步传输),第三个参数因为默认是true(异步)所以可以省略
前端页面代码
let xhr = new XMLHttpRequest();
xhr.open('get','URL?value=string');//将拼串的URL放置此
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.status === 200){
//接受响应的操作
}
}
接收响应操作
readyState代表XHR对象所处于的状态,他有5个值
- readyState = 0,尚未调用open方法
- readyState = 1,调用了open方法,但数据还没有发送
- readyState = 2,数据已经发送,但没有接收到响应
- readyState = 3,接收到部分响应
- readyState = 4,接收到全部响应,可以查看
XHR对象接收到全部响应后,数据会填满对象,此时需要调用onreadystatechange方法来监控XHR所处于的状态,因为每当readyState数值发生变化,都会调用一次onreadystatechange方法
简单优化
我们一般在readyState = 4状态时操作响应数据,并且我们会监控服务端返回的状态码
当以2开头时,服务器返回的响应即为正确,除此之外,304的意思为页面正确且会重定向到浏览器已有的缓存文件,所以我们可以将接收操作处改为
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304)){
//接受响应的操作
}
}
Node服务器代码
app.get('/',(req,res)=>{
console.log(req.query);//get请求使用query参数接收
res.send('ok')
});
原生AJAX发送post请求
- post与get方法不同的点在于,post方法发送的数据在请求体中,并且需要设置请求头
前端页面代码
let xhr = new XMLHttpRequest();
xhr.open('post','http://localhost:8088');//不需要拼串了
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');//设置请求头
xhr.send('key=value'); //发送数据(请求体)
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.staus === 200){
//接受响应的操作
}
}
与前端页面一样,后端post也与get请求略微不同
- 首先,后端接受post请求的参数并不是query而是body
- 其次,Node并不能直接解析post请求,而是需要通过中间件
Node服务器代码
app.use(express.urlencoded({extended:true}))//我使用的是express内置的中间件
app.post('/',(req,res)=>{
let {key} = req.body; //我们可以直接使用解构赋值来获取body中相应的值
console.log({key});
res.send('ok');
})
jQuery封装AJAX
- jQuery本身对AJAX进行了封装,有两种写法,效果都一样 前端页面代码
标准写法:
$.ajax('请求的地址',{
method:'', //请求的方法
data:{}, //请求的数据
dataType:'', //响应的数据类型
success:(result)=>{}, //成功回调
error:(err)=>{} //失败回调
})
简写:
$.get/post('请求地址',data,(data(响应的数据),success,xhr)=>{},dataType)
Promise封装AJAX发送get请求
- 我们都知道Promise是前端进行异步操作的一种方法,而且通过上面的知识,我们应该差不多了解了AJAX的基本用法,我们现在就可以根据jQuery的格式简单封装一下
前端页面代码
let sendAjax = function (method,url,data){
return new Promise(()=>{
let xhr = new XMLHttpRequest();
//判断是’get‘请求还是’post‘请求
if(method.toLowerCase() === 'get'){
url += ('?' + data); //get请求需要进行拼串操作
xhr.open(method,url);
xhr.send();
}else if(method.toLowerCase() === 'post'){
xhr.open(method,url);
xhr.setRequestHeader('content-Type','application/x-www-form-urlencoded')
xhr.send(data);
}
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304)){
//接受响应的操作
resolve(); //返回成功
}else{
reject(); //返回失败
}
}
})
}
function clickB(){
sendAjax('post','http://localhost:8088','a=1')
}
优化
- 我们在上面已经进行了简单的封装,但我们输入数据一般都是以对象的方式进行存储,那么,我们就需要将对象转化为URL的格式
- 这里我们主要使用reduce累计的特性,来达到获取对象中所有属性值的目的
let keys = Object.keys(data); //获取所有的key值
if(data instanceof Object){ //判断是否为对象,如果不是可以将其转化为对象
data = keys.reduce((pre,now)=>{ //使用reduce方法累计附加对象中的key和value
return pre += `${now}=${data[now]}&`;//使用模板字符串来简化写法
},'')
}
最终版
let value = {
name:'sys',
age:18
}
let sendAjax = function (method,url,data){
return new Promise(()=>{
let xhr = new XMLHttpRequest();
let keys = Object.keys(data);
if(data instanceof Object){
data = keys.reduce((pre,now)=>{
return pre += `${now}=${data[now]}&`;
},'')
}
if(method.toLowerCase() === 'get'){
url += ('?'+ data);
xhr.open(method,url);
xhr.send();
}else
if(method.toLowerCase() === 'post'){
xhr.open(method,url);
xhr.setRequestHeader('content-Type','application/x-www-form-urlencoded')
xhr.send(data);
}
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.staus === 200){
//接受响应的操作
}
}
})
}
function clickB(){
sendAjax('get','http://localhost:8088',value)
}
借鉴:《JavaScript高级程序设计》 + 网上查找 + 自己的理解
如有错误,希望提出
希望大家都能早日拿到心仪的offer,加油,共勉