轮询与长轮询

轮询

"""
轮询即轮番询问
让浏览器定时(例如每隔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>
posted @ 2020-03-16 17:09  ylpb  阅读(264)  评论(0编辑  收藏  举报