一.原理:
- 前端异步ajax的目的是释放等待且当前操作是独立行为,对后续操作没有直接干涉;
- 服务器端异步的目的是: 避免大量资源被单一线程占用/闲置,进一步压榨硬件性能,但部分系统硬件都有上限锁,只是这种异步更进一步逼近这个上限。同时,前端请求页面的时候,也可以避免长时间的等待。
- 服务器端异步问题其实本质问题是:后端如何给前端主动推送消息?有两种方式:
- Websocket。
- 前端定时访问。
二.场景
- 前端发送处理请求后,后端开始处理
- 后端处理时间较长,估计有10几秒(时间每次都不太确定)才能处理完
- 后端处理完后,前端在页面上显示处理完成
三. 初步设计
- 前端第一次访问页面的时候,采用http访问
- 后端接到请求,将快速的返回一个页面,此时,把很消耗时间的数据运算,查询单独开线程进行处理;
- 前端显示页面,与单独开线程处理相关的数据此时是空的,因为后端没有返回值回来。
- 后端此时处理完了数据,将数据存入redis。(数据实时性不是很要紧)(看各自业务,我的业务是这样的,如果你的不是,可以自己设计);
- 前端此时如果页面没有关闭,没有重新加载,那么,会ajax定时访问一个接口,此接口作用是从redis取出数据。这就要求前端要把所有的需要的数据先存入一个变量数组中,然后访问的时候才可以重新找到刚刚写入redis的对应数据。(看各自业务)
- 后端收到ajax,查询redis,封装好后返回给前端
- 前端收到消息,执行回调函数,将数据通过操作dom的方式填入指定的空格。
- 完成流程,此后关闭ajax定时操作
四. 应用技术
- Ajax
- 后台多线程,callback(可能用不上,开个线程就好了)
- 前端定时发送信息
- 前端获取对应dom,根据vid之类的(我们的需求中的唯一标识)填入指定的数据。涉及dom的刷新。
五. 编码
不全写,简单把技术的关键点说一下:
- 前端定时发送请求设置:
其中,test可以改为自己的ajax函数:
function asyncGetVideoNum(){
$.ajax({
type : "post",
async : false,
url : "/post/接口",
timeout:1000,
data : {
"参数1": 参数变量,
"参数2": 参数变量,
"参数3": 参数变量
},
success:function(result){
var re = JSON.parse(result) //我的后端返回的是json字符串,要转化为json对象。
var stopFlag = 0; //一个定时器关闭的控制状态变量
if(re.status==200){ //返回结果成功
var resultMap = re.data; //循环处理回来的数据
for(var item in resultMap){
var divOfVideoNum = item+'vn'; //动态拼接id,方便控制div元素
if(resultMap[item]!=-1+''){
$("#"+divOfVideoNum).text(resultMap[item]);//要刷新的div
stopFlag += 1;
console.log("刷新成功");
}
}
if(stopFlag == page.size){
clearInterval(stopId);//清除定时器
}else{
stopFlag = 0; //定时器状态为0,表示还要继续发送请求
}
}
},
error: function() {
console.log("失败,请稍后再试!");
}
});
}
});
- 代码关键:
- 当传输的数据量很大的时候,type应该使用post,用get会报错400,浏览器出异常,超出url长度
- 前端可以直接传输数组,而不用转化为json,后端可以接受数据,采用@REQUESTparam(“数组名[]”)的形式获取数据,并且,后端可以识别数组,并且自动注入list中。这里注意的地方有:数组名会自动加一个[],所以第一次接收数据报错了,看request的paramMap才找到问题。然后是数组可以自动注入list,挺智能的。
- js的ID选择器中如何拼接变量?直接“#”+变量名就好了。Js编译器眼中,没有特殊意义的变量都只是字符串而已。
六. 测试
- 测试速度,测试异步刷新效果,准确重新加载,数据没有错乱。
七. 优化
- 前端如果不是定时异步,而是change异步,如文本框的搜索提示,就是一种大量发送异步的情况,如何确保接收到的返回值就是我需要的。
答: - 采用时间戳,前端检查返回的消息是否是当前时间戳之后的,如果是,那就是可以更新,否则就是延后的请求。
- 对于需要的返回值,进行一个对比检验即可知道那些要显示