实时响应数据之短轮询和长轮询

实时响应数据

在Web应用开发中,我们会经常需要实时响应数据,例如:网页聊天室、实时更新网页在线人数等很多的应用场景。我们前后端数据的交互,通常使用ajax进行交互,所以下面的两种方法都是基于ajax交互技术。

短轮询

下面我先给大家一个应用场景:网页聊天室,对方发信息过来,我们的前端界面必须马上响应出来,我们发信息过去,对方也要马上响应到前端界面。

解决问题的思路:
1.前端要不停地向后端发送请求(ajax请求)
2.两个人的聊天记录可以放置于缓存中(redis)
3.每次ajax访问请求,把缓存中的聊天数据重新响应到前端

短轮询,不停的询问请求,而且每次请求时间特别短,这就意味着前端要每隔很短的时间就发送一次ajax请求,不停的响应缓存中的数据到前端界面。这势必会增加服务器的压力,但是我还是将这样一种思想用代码展示下。

 //刷新聊天
    function flush() {
        $.ajax({
            url: "text",
            type: "POST",
            data: {name:name},
            async: false,
            success: function (data) {
                $(data).each(function () {
                //成功回调函数,遍历data数据,进行前端渲染,这里自由发挥
                })
            },
            error: function (XMLHttpRequest) {
                alert(XMLHttpRequest.status);
            }
        });
        setTimeout("flush()",1000); //一秒中后再次调用flush()方法 ,就这样不停的短轮询
    }

后端的请求大家就自由发挥了,你想要返回什么数据就返回什么数据,前端想怎么渲染就怎么渲染。
大家可以看到,短轮询以如此速度发送请求将给服务器造成巨大的压力,所以我推荐大家使用长轮询,下面就给大家介绍。

长轮询

长轮询概念:前端向服务器发送请求,一直保持着请求,直到服务器响应才结束这次请求,相比于短轮询的发送请求次数,可以说长轮询是巨大的优化。

类似于:好友发送消息给我,才局部响应到我的聊天界面,不用一直去请求刷新。

//这是前端的ajax请求
 function longConnection() {
            $.ajax({
                url : "long",
                type : "POST",
                success : function(data) {
                    if(data=="flush"){
                        alert("刷新");//后端请求判断返回字符串
                    }
                    longConnection(); //结束这次请求后,再次调用本身方法
                },
                error : function(XMLHttpRequest) {
                    alert(XMLHttpRequest.status);
                    longConnection();//发生异常错误后再次发起请求
                }
            });
        }
//光看前端的ajax请求看不出什么,看看后面的后端请求

@Controller
public class LongConnectionController {
@Autowired
private RedisTemplate redisTemplate;
private static final long TIMEOUT = 20000;// 超时时间设置为20秒,这个时间随便你设置
//我设置20s,代表我这次请求最多维持20s

@RequestMapping("/long")
@ResponseBody
public  String longConnection(HttpSession session)throws Exception{
    String msg="";
    long requestTime = System.currentTimeMillis(); //获取进入请求时间
        while(System.currentTimeMillis()-requestTime<TIMEOUT){
        //我这是从redis读取一个标志,如果不为null,代表我接受到新消息,我就得刷新
            String o =(String) redisTemplate.opsForHash().get("one", flag);
            if(o!=null){
            //读取后就清空标志,下次有人发消息再设置
                redisTemplate.opsForHash().delete("one",flag);
                msg="flush";  //msg复制“flush”,前端判断渲染界面
                break;  //退出循环,马上响应
            }
            else {
                msg="timeOut";
                Thread.sleep(1000);  //休眠1s
            }
            }
    return msg;
}
}

我解释下上面的代码:
前端发送ajax请求过来,后端并不会马上响应,自然维持了这次请求的时间。后端请求设置了20s的超时时间,用一个while循环加时间戳循环20s,当判断有新消息时,马上break出while循环,返回数据给前端。

所以只要判断没有新消息,while循环就会维持20s,即这个请求会维持20s,当然我们可以设置更长的时间,这都不影响。

聊天室效果展示

在这里插入图片描述
在这里插入图片描述
挺好玩的,关于实时接收信息还有很多方法,以上就是介绍两种,欢迎大家评论!

猜你喜欢

转载自blog.csdn.net/gtahxm1314/article/details/107965630