轮询
"""
轮询即轮番询问
让浏览器定时(例如每隔5s中发送一次)通过ajax偷偷滴朝服务端发送请求获取数据
不足之处
消息延迟
请求次数过多 损耗资源严重
效率低 基本不用
"""
长轮询
"""
服务端给每个客户端创建一个队列,让浏览器通过发送ajax请求,请求各自队列中的数据,如果没有数据则会阻塞但是不会一直阻塞,利用timeout参数加异常处理的形式最多阻塞30s之后返回,浏览器判断是否有数据,没有则继续发送请求(目前网页版的微信和qq用的还是这个原理)
优点:在无消息的情况下不会频繁的请求,耗费资源小。
缺点:服务器hold连接会消耗资源,返回数据顺序无保证,难于管理维护。
"""
长轮询实现简易版群聊功能
# 长轮询实现聊天室功能
url(r'^home/$',views.home),
url(r'^send_msg/$',views.send_msg),
url(r'^get_msg/$',views.get_msg)
# 定义一个存储用户队列的字典
q_dict = {} # {'jason':队列}
def home(request):
# 获取自定义的唯一标示
name = request.GET.get('name')
# 给每个用户生成一个对应的队列对象
q_dict[name] = queue.Queue()
return render(request,'home.html',locals())
def send_msg(request):
if request.method == 'POST':
# 获取用户输入的内容
msg = request.POST.get('msg')
# 将该消息给所有的队列发送一份
for q in q_dict.values(): # 循环获取所有客户端浏览器对应的队列对象
q.put(msg)
return HttpResponse('OK')
def get_msg(request):
# 获取用户唯一标示 去用户自己对应的队列中获取数据并非返回
name = request.GET.get('name')
# 去全局字典中获取对应的队列
q = q_dict.get(name)
# ajax交互一般用的都是字典格式
back_dic = {'status':True,'msg':''}
# 异常处理 获取队列中的数据
try:
data = q.get(timeout=10) # 等10s
back_dic['msg'] = data
except queue.Empty as e:
# 将状态改为False 然后让浏览器再来要数据
back_dic['status'] = False
return JsonResponse(back_dic)
<h1>聊天室:{{ name }}</h1>
<div>
<input type="text" id="i1">
<button onclick="sendMsg()">发送</button>
</div>
<h1>聊天纪录</h1>
<div class="record">
</div>
<script>
function sendMsg() {
$.ajax({
url:'/send_msg/',
type:'post',
data:{'msg':$('#i1').val(),'csrfmiddlewaretoken':'{{ csrf_token }}'},
success:function (args) {
}
})
}
// 书写ajax偷偷的请求数据 自己跟自己的队列去要
function getMsg() {
$.ajax({
url:'/get_msg/',
type:'get',
dataType:'JSON',
// 携带唯一标示
data:{'name':'{{ name }}','csrfmiddlewaretoken':'{{ csrf_token }}'},
success:function (args) {
// 判断是否有数据回来了 如果没有 则继续调用自身
if(args.status){
// 有消息则做消息展示
{#alert(status.msg)#}
// 将消息通过DOM操作展示到前端页面
// 1 创建标签
var pEle = $('<p>');
// 2 添加文本内容
pEle.text(args.msg);
// 3 将标签添加到页面对应的位置
$('.record').append(pEle)
}
// 继续调用自己
getMsg()
}
})
}
// 页面加载完毕之后 就应该循环触发 onload 所有看似不起眼的知识点都是很有用的
$(function () {
getMsg()
})
</script>