zoukankan      html  css  js  c++  java
  • web长轮询

    轮询

    假设有这么一个场景:要做一个在线投票的系统,那么我的浏览器看的的投票数量应该是动态变化的,一旦有其他人投票,那么我的浏览器显示的投票数应该会发生改变,那么这个场景应该怎么做呢?第一反应想到的就是每隔一段时间去发请求拿最新数据,比如每隔2s通过ajax偷偷发请求去获取最新票数然后渲染到我的浏览器。
    flask_test.py

    from flask import Flask, render_template, jsonify, request
    
    app = Flask(__name__)
    app.deug = True
    
    VOTE_LIST = [
        {'name': '小明', 'count':3, 'id':1},
        {'name': '小红', 'count':5, 'id':2},
        {'name': '小花', 'count':6, 'id':3}
    ]
    
    @app.route('/index')
    def index():
        return render_template('index.html')
    
    @app.route('/get_vote')
    def get_vote():
        return jsonify(VOTE_LIST)
    
    @app.route('/vote/')
    def vote():
        nid = request.args.get('nid')
        for item in VOTE_LIST:
            if item['id'] == int(nid):
                item['count'] += 1
        return 'vote success'
    
    
    if __name__ == '__main__':
        app.run(host='0.0.0.0')
    

    index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            .box1{
                 100px;
                height: 100px;
                background-color: red;
            }
            .box2{
                 100px;
                height: 100px;
                background-color: green;
            }
        </style>
    
    </head>
    <body>
        <div id="app">
            <ul v-for="item in vote_list">
                <li>{[ item.name ]}({[ item.count ]})</li>
            </ul>
        </div>
    
    
    
        <script src="/static/jquery-3.3.1.min.js"></script>
        <script src="/static/vue.min.js"></script>
        <script>
            var app = new Vue({
                el: '#app',
                delimiters:['{[', ']}'],
                data: {
                    vote_list:[],
                    cl:null
                },
                created() {
                    var that = this;
                    this.cl = setInterval(function () {
                        $.ajax({
                            url: '/get_vote',
                            type: 'get',
                            success: function (arg) {
                                console.log(arg)
                                that.vote_list = arg
                            }
                        })
                    }, 2000)
                }
    
            });
    
    
        </script>
    </body>
    </html>
    

    这样虽然可以完成需求,但是还存在几个问题:

    1. 实时性没法保证,因为每隔2s才拿数据,即使在第1s的时候有人投票了,那么也要再过1s才能拿到数据
    2. 为了实时性更好,发送请求的时间缩短,但是这样又会明显增加服务器压力

    那么,有没有这么一种方式:每隔比较长的时间去发一次请求,如果期间有人投票,那么立即返回数据,如果没有人投票,则就等待设定的那段比较长的时间请求再结束。
    现在问题就转化为我去发一个请求,在这个请求里面应该监测是否有人投票,或者说监测vote_list是否有变化,有变化就立即返回。那怎么去监测呢?写一个死循环去监测一个变量的内容是否变化?当然这样肯定是可以的,但是比较low,在这里可以借助队列来实现。我们把这种方式称之为长轮询

    长轮询

    flask_test.py

    import uuid
    
    from flask import Flask, render_template, jsonify, request, session
    from queue import Queue
    
    app = Flask(__name__)
    app.deug = True
    app.secret_key = 'asdasdas'
    
    VOTE_LIST = [
        {'name': '小明', 'count':3, 'id':1},
        {'name': '小红', 'count':5, 'id':2},
        {'name': '小花', 'count':6, 'id':3}
    ]
    
    QUEUE_DICT = {}
    
    @app.route('/index')
    def index():
        uid = str(uuid.uuid4())
        session['uid'] = uid
        QUEUE_DICT[uid] = Queue()
        return render_template('index.html')
    
    @app.route('/first_get_vote')
    def first_get_vote():
        return jsonify(VOTE_LIST)
    
    
    @app.route('/get_vote')
    def get_vote():
        global VOTE_LIST
        uid = session.get('uid')
        q = QUEUE_DICT[uid]
        try:
            VOTE_LIST = q.get(timeout=5)
        except Exception:
            VOTE_LIST = VOTE_LIST
        return jsonify(VOTE_LIST)
    
    @app.route('/vote/')
    def vote():
        nid = request.args.get('nid')
        for item in VOTE_LIST:
            if item['id'] == int(nid):
                item['count'] += 1
        for q in QUEUE_DICT.values():
            q.put(VOTE_LIST)
        return 'vote success'
    
    
    if __name__ == '__main__':
        # 开启多线程
        app.run(host='0.0.0.0', threaded=True)
    

    index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            .box1{
                 100px;
                height: 100px;
                background-color: red;
            }
            .box2{
                 100px;
                height: 100px;
                background-color: green;
            }
        </style>
    
    </head>
    <body>
        <div id="app">
            <ul v-for="item in vote_list">
                <li>{[ item.name ]}({[ item.count ]})</li>
            </ul>
        </div>
    
    
    
        <script src="/static/jquery-3.3.1.min.js"></script>
        <script src="/static/vue.min.js"></script>
        <script>
            var app = new Vue({
                el: '#app',
                delimiters:['{[', ']}'],
                data: {
                    vote_list:[],
                    cl:null
                },
                methods:{
                    get_vote(){
                         var that = this;
                        $.ajax({
                            url: '/get_vote',
                            type: 'get',
                            success: function (arg) {
                                console.log(arg)
                                that.vote_list = arg
                                // 在函数里面调用函数自己,递归
                                that.get_vote();
                            }
                        })
                    }
                },
    
                created() {
                    var that = this;
                    $.ajax({
                            url: '/first_get_vote',
                            type: 'get',
                            success: function (arg) {
                                that.vote_list = arg
                            }
                        })
                    this.get_vote()
                }
    
            });
    
    
        </script>
    </body>
    </html>
    

  • 相关阅读:
    MOSS007 服务器的配置
    服务器日志查询代码
    MOSS2007页面UI定制(无代码上手)
    远程服务器监控程序浅谈
    CoreChart安装使用分享(附 安装文件CoreChart.wsp)
    Tree WebPart的介绍
    思科金牌、银牌代理商名录
    如何让你的移动硬盘或者U盘变得百毒不侵呢?
    CCNA网络工程师面试题
    ICMP报文的各种格式和种类
  • 原文地址:https://www.cnblogs.com/longyunfeigu/p/9491496.html
Copyright © 2011-2022 走看看