代码之家  ›  专栏  ›  技术社区  ›  barciewicz

如何在不使用线程/后台作业的情况下,使服务器端循环无止境且无阻塞?

  •  0
  • barciewicz  · 技术社区  · 6 年前

    我需要一个无休止的循环来运行服务器端并在每次迭代中发出一些信息。

    另外,我需要确保它只启动一次—最好是在服务器启动时—而不是由使用该应用程序的不同用户引起的。

    任务如下:

    @app.route('/refresh_games_list_periodically')
    def refresh_games_list_periodically():
        while True:
            response = {
                'games_list': games_manager.get_nonexpired_games(),
            }
            socketio.emit('games_list_refreshed', response)
            time.sleep(1)
    

    每当呈现“index.html”时,它就会启动:

    @app.route('/')
    def index(): 
        return render_template('index.html')
    

    fetch("{{url_for('refresh_games_list_periodically') }}")
    

    完整代码:

    import time
    
    from flask import (
        Flask, 
        render_template, 
        jsonify,
        request,
    )
    from flask_socketio import SocketIO, emit
    
    from minesweeper import Game, GamesManager
    
    games_manager = GamesManager()
    
    app = Flask(__name__)
    socketio = SocketIO(app)
    
    @app.route('/refresh_games_list_periodically')
    def refresh_games_list_periodically():
        while True:
            response = {
                'games_list': games_manager.get_nonexpired_games(),
            }
            socketio.emit('games_list_refreshed', response)
            time.sleep(1)
    
    @app.route('/')
    def index(): 
        return render_template('index.html')
    

    目前的问题是,每当一个新用户输入'index.html',循环的另一个迭代将开始运行旧的。

    我曾尝试使用一些布尔标记将视图标记为已调用,但无法在Flask上下文中正确地获得它。

    然后我想我可以 refresh_games_list_periodically 一个普通的函数,不是一个视图,只需在我的Flask应用程序中调用它就可以了。但是后来 while 循环将被阻止,并且不会呈现任何页面:

    import time
    
    from flask import (
        Flask, 
        render_template, 
        jsonify,
        request,
    )
    from flask_socketio import SocketIO, emit
    
    from minesweeper import Game, GamesManager
    
    games_manager = GamesManager()
    
    app = Flask(__name__)
    socketio = SocketIO(app)
    
    refresh_games_list_periodically()
    
    def refresh_games_list_periodically():
        while True: # WILL BLOCK
            response = {
                'games_list': games_manager.get_nonexpired_games(),
            }
            socketio.emit('games_list_refreshed', response)
            time.sleep(1)
    
    @app.route('/')
    def index(): 
        return render_template('index.html')
    

    0 回复  |  直到 6 年前
        1
  •  0
  •   Joran Beasley    6 年前
    thread = threading.Thread(target=refresh_games_list_periodically)
    thread.start() 
    

    我想。。。我想这不是一个好主意,但你可能更好地运行你的套接字循环在一个进程和你的烧瓶应用程序分开