Двунаправленное общение с веб-сокетами в Quart - PullRequest
0 голосов
/ 18 марта 2020

Я хочу иметь возможность использовать WebSocket в Quart для получения любых отправленных сообщений и отправки любых сообщений, которые мне могут понадобиться. Нет гарантии, что сообщения будут чередоваться между отправкой и получением.

Например, Страница учебника Quart по WebSockets содержит следующий фрагмент:

@app.websocket('/api/v2/ws')
@collect_websocket
async def ws(queue):
    while True:
        data = await queue.get()
        await websocket.send(data)

Почему-то я Я хочу изменить код в while True l oop, чтобы я мог проверить, есть ли какие-либо данные, которые будут получены, но если нет, я вместо этого проверю очередь.

Я бы хотелось бы иметь возможность ждать получения в сокете, только если есть что-то для получения (что, возможно, могло бы быть достигнуто, если бы в методе receive был параметр timeout), но это не вариант.

Итак, как я могу await WebSocket для обновлений, а также await что-то еще для обновлений ?

1 Ответ

0 голосов
/ 18 марта 2020

Автор Quart отвечает на это в посте Websockets in Quart , в котором содержится фрагмент, который я немного изменил, чтобы получить следующее:

import asyncio

from quart import copy_current_websocket_context, Quart, websocket

app = Quart(__name__)

@app.websocket('/ws')
async def ws():

    async def consumer():
        while True:
            data = await websocket.receive()

    async def producer():
        while True:
            await asyncio.sleep(1)
            await websocket.send(b'Message')

    consumer_task = asyncio.ensure_future(consumer())
    producer_task = asyncio.ensure_future(producer())
    try:
        await asyncio.gather(consumer_task, producer_task)
    finally:
        consumer_task.cancel()
        producer_task.cancel()

Фрагмент создает два различные функции asyn c со своими собственными while True циклами. Затем Python asyncio.ensure_future используется для создания двух различных Task с для работы. Наконец, asyncio.gather вызывается для одновременной оценки задач.

Определяя две задачи внутри определения ws, они действуют как замыкания, то есть имеют доступ к websocket «специальному» глобальному объект, который имеет смысл только внутри функции ws. Если вы хотите определить эти функции вне тела функции ws, возможно, потому, что вам нужно вызывать их из других источников, вы можете использовать функцию copy_current_websocket_context из Quart при передаче их в ensure_future :

consumer_task = asyncio.ensure_future(
    copy_current_websocket_context(consumer)()
)
...