gpt4 book ai didi

javascript - 与 sanic websockets 的双向通信,无需永远等待

转载 作者:行者123 更新时间:2023-11-30 13:55:01 35 4
gpt4 key购买 nike

我问了these questions关于 sanic 中的 websockets。这是跟进。

以下内容让我向我的 websocket 客户端广播消息:

from sanic import Sanic, response
from sanic.websocket import WebSocketProtocol
import asyncio
import time

app = Sanic()

@app.websocket('/feed')
async def feed(request, ws):
while True:
now = time.time()
data = f'message: {now}'
print(data)
await ws.send(data)
await asyncio.sleep(1)

@app.route('/')
async def handle_request(request):
return response.html("""
<html><head>
<script>
const ws = new WebSocket("ws://" + location.host + '/feed');
ws.onmessage = event => {
let e = event;
console.log(e.data);
let out = document.getElementById('out');
out.innerHTML += `<li><p>${e.data}</p></li>`;
}
document.querySelector('form').addEventListener('submit', (event) => {
event.preventDefault();
let message = document.querySelector("#in").value;
ws.send(message);
document.querySelector("#in").value = "";
})
</script>
</head>
<body><h1>Main</h1>
<div id="in"><form><input type="text" method="post"></form></div>
<div><ul id="out"></ul></div>
</body>
</html>
""")

app.run(host="0.0.0.0", port=8000)

我可以确认服务器既定期向客户端发送消息,又能够接收某种类型的消息。

在服务器上:

[2019-08-12 22:06:27 -0500] - (sanic.access)[INFO][127.0.0.1:49028]: GET http://localhost:8000/  200 714
message: 1565665587.4367297
message: 1565665588.4373734
message: 1565665589.4389973
message: 1565665590.440603
message: 1565665591.4414358
message: 1565665592.441888
message: 1565665593.443465
[2019-08-12 22:06:34 -0500] - (sanic.access)[INFO][127.0.0.1:49036]: GET http://localhost:8000/ 200 714
message: 1565665594.362771
message: 1565665595.3643198
message: 1565665596.3655813
message: 1565665597.3671694

在客户端:

enter image description here

但是,由于以下几个原因,这对我来说没有意义:

  1. 当我提交表单时,我实际上看不到表单的内容提交,只是有一个GET请求。
  2. 我看到一个 GET 请求,但我的表单明确显示为 POST。
  3. event.preventDefault() 被使用,我仍然看到表单提交时的完整页面刷新。

而且,我真正想要的是双向通信。因此,除了 ws.send(data) 之外,我还将在方法中使用 new = await ws.recv() 并捕获输入。

@app.websocket('/feed')
async def feed(request, ws):
while True:
now = time.time()
data = f'message: {now}'
print(data)
await ws.send(data)
new = await ws.recv() # this is the only change
print(new)
await asyncio.sleep(1)

但是现在,我不再持续向客户端发送数据了。相反,进程挂起,等待我的 ws.recv(),即使客户端没有发送任何东西也是如此。

[2019-08-12 22:13:52 -0500] [12920] [INFO] Starting worker [12920]
[2019-08-12 22:13:56 -0500] - (sanic.access)[INFO][127.0.0.1:49086]: GET http://localhost:8000/ 200 714
message: 1565666037.0688074
[2019-08-12 22:14:03 -0500] - (sanic.access)[INFO][127.0.0.1:49090]: GET http://localhost:8000/ 200 714

在我再次提交表单之前,不会再发送消息

我如何进行双向通信,将数据传回 /feed 端点,但无需等待就可以连续传递?

最佳答案

您需要将消费者和生产者分开,这里有一个如何做到这一点的示例:

from sanic import Sanic, response
import asyncio
import time

app = Sanic()


async def _consumer_handler(ws):
print('consumer_handler')
while True:
message = await ws.recv()
print('message arrived', message)


async def _producer_handler(ws):
print('producer_handler')
while True:
now = time.time()
data = f'message sent: {now}'
print(data)
await ws.send(data)
await asyncio.sleep(1)


@app.websocket('/feed')
async def feed(request, ws):
consumer_task = asyncio.ensure_future(
_consumer_handler(ws))
producer_task = asyncio.ensure_future(
_producer_handler(ws))
done, pending = await asyncio.wait(
[consumer_task, producer_task],
return_when=asyncio.FIRST_COMPLETED,
)
for task in pending:
task.cancel()


@app.route('/')
async def handle_request(request):
return response.html("""
<html><head>
</head>
<body><h1>Main</h1>
<div><form><input id="in" type="text" method="post"></form></div>
<div><ul id="out"></ul></div>
</body>
<script>
const ws = new WebSocket("ws://" + location.host + '/feed');
ws.onmessage = event => {
let e = event;
console.log(e.data);
let out = document.getElementById('out');
out.innerHTML += `<li><p>${e.data}</p></li>`;
}
document.querySelector('form').addEventListener('submit', (event) => {
event.preventDefault();
let message = document.querySelector("#in").value;
ws.send(message);
document.querySelector("#in").value = "";
})
</script>
</html>
""")

app.run(host="0.0.0.0", port=8000)

要在消费者和生产者之间进行通信,您需要使用 pubsub,或定期检查新消息(并且您需要将消息存储在某个地方,例如可以使用 redis)。

一些有用的链接:

关于javascript - 与 sanic websockets 的双向通信,无需永远等待,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57470718/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com