【发布时间】: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