【问题标题】:Sanic Websocket Asynchronous ManagementSanic Websocket 异步管理
【发布时间】:2019-11-26 07:54:23
【问题描述】:

我有一个 Sanic 应用程序。它提供一个带有一些可变本地状态的 html 页面。根据状态,用户通过 websocket 收到不同的响应:

import time
import random
import simplejson as json
from sanic import Sanic, response
from sanic.websocket import WebSocketProtocol

flowers = {
    'purple': 'aster',
    'red'   : 'rose',
    'white' : 'daisy'
}

def random_quality():
    return random.choice(['Nice', 'Beautiful', 'Fragrant', 'Vivid'])

app = Sanic()

@app.route('/')
def handle_request(_req):
    return response.html("""
    <!DOCTYPE html>
    <html lang="en" dir="ltr">
    <head>
      <meta charset="utf-8">
    </head>
    <body>

      <div id="current">Select color</div><br>
      <input type="radio" name="flower" onchange="notifyColor(this.value)" value="purple" />Purple<br>
      <input type="radio" name="flower" onchange="notifyColor(this.value)" value="red" />Red<br>
      <input type="radio" name="flower" onchange="notifyColor(this.value)" value="white" />White<br>

      <script type="text/javascript">
        var ws;
        var notifyColor = (color) => {
          ws.send(color);
        }
        window.onload = () => {
          ws = new WebSocket('ws://localhost:3000/api/');
          var quality;
          var flower;

          ws.onmessage = (e) =>{
            let res = JSON.parse(e.data);
            if (res.hasOwnProperty("flower")) {
              flower = res.flower;
            }
            quality = res.quality
            document.getElementById("current").innerText = quality + ' ' + flower;
          }
        }
      </script>

    </body>
    </html>
    """)

@app.websocket('/api/')
async def cache_api(_req, ws):
    while True:
        color = await ws.recv()
        flower = flowers[color]
        quality = random_quality()
        res = json.dumps({'flower': flower, 'quality': quality})
        await ws.send(res)

app.run(debug=True, port=3000, protocol=WebSocketProtocol)

但是,我想在循环中定期向用户推送部分数据,而用户仍然可以更改本地状态并通知服务器:

# pseudocode-ish
@app.websocket('/api/')
async def cache_api(_req, ws):
    while True:
        color = await ws.recv()
        flower = flowers[color]
        res1 = json.dumps({'flower': flower})
        await ws.send(res1)
    #---------------------------------------------#
    # AND ALSO SIMULTANEOUSLY ("ASYNCHRONOUSLY"?) #
    #---------------------------------------------#
    while True:
        quality = random_quality()
        res2 = json.dumps({'quality': quality})
        await ws.send(res2)
        time.sleep(2)

如何做到这一点?我必须使用中间件功能吗?如果是,如何写?在我的情况下,使用多个 websocket 或不同的 api 端点是不可能的。

【问题讨论】:

    标签: javascript python asynchronous websocket sanic


    【解决方案1】:

    一般的、简化的方法是这样的

    @app.websocket('/api/')
    async def cache_api(_req, ws):
        async def _operation_one():
            while True:
                color = await ws.recv()
                flower = flowers[color]
                res1 = json.dumps({'flower': flower})
                await ws.send(res1)
    
        async def _operation_two():
            while True:
                quality = random_quality()
                res2 = json.dumps({'quality': quality})
                await ws.send(res2)
                await asyncio.sleep(2)
    
        await asyncio.gather([
            _operation_one(),
            _operation_two(),
        ])
    

    【讨论】:

      猜你喜欢
      • 2020-09-13
      • 1970-01-01
      • 1970-01-01
      • 2013-01-30
      • 2013-04-27
      • 2018-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多