首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Sanic Websocket异步管理

Sanic Websocket异步管理
EN

Stack Overflow用户
提问于 2019-11-26 15:54:23
回答 1查看 216关注 0票数 0

我有一个Sanic应用。它提供具有某些可变本地状态的html页面。根据状态的不同,用户在websocket上会收到不同的响应:

代码语言:javascript
复制
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)

但是,我希望在循环中定期将部分数据推送给用户,同时用户仍然可以更改本地状态并通知服务器:

代码语言:javascript
复制
# 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)

如何做到这一点呢?我必须使用中间件函数吗?如果是,该如何编写它们?在我的例子中,使用多个websockets或不同的api端点是不可能的。

EN

回答 1

Stack Overflow用户

发布于 2019-11-27 00:02:19

一般的、简化的方法如下所示

代码语言:javascript
复制
@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(),
    ])
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59046130

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档