This is my first experience with websockets, and I'm not completely sure I am doing everything correctly. However, when reloading the web browser, the reconnects to the websocket. When this happens I have a list of messages from previous sessions and I send them back. At the moment, there are only 3, but the browser does not receive all 3 of them.
I am using FastAPI, and my send/receive code looks like this:
@app.websocket_route("/ws")
async def websocket_endpoint(websocket: WebSocket):
ws_active = False
# when establishing the websocket, query the devices online
# but only if it's the first connection
device_report()
# accept the websocket connection
await websocket.accept()
ws_active = True
# Push message history to client
async def send(message):
nonlocal ws_active
await push_messages(websocket)
try:
while ws_active:
# Check if there are any messages in the queue
if not queue().empty():
message = await queue().get()
print('get: ' + message)
if ws_active:
await websocket.send_text(message)
# Wait for new messages to arrive in the queue
message = await queue().get()
if ws_active:
print('get2: ' + message)
await websocket.send_text(message)
except WebSocketDisconnect:
try:
await websocket.close()
ws_active = False
except:
pass
async def receive():
nonlocal ws_active
try:
while ws_active:
data_in = await websocket.receive_json()
print(data_in)
except WebSocketDisconnect:
try:
await websocket.close()
ws_active = False
except:
pass
try:
await asyncio.gather(send('{asd:asd}'), receive())
except:
pass
the function push_messages is simple and it just takes the array of data and puts them in the queue.
async def push_messages(self, websocket: WebSocket):
for message in self.can_messages:
print('push: ' + message)
await self.message_queue.put(message)
for message in self.all_messages:
await self.message_queue.put(message)
Reloading the browser I see these output on the python console:
push: {"type": "can", "msg": "Supervisor reported online."}
push: {"type": "can", "msg": "ECU 1 reported online."}
push: {"type": "can", "msg": "ECU 2 reported online."}
get2: {"type": "can", "msg": "Supervisor reported online."}
get: {"type": "can", "msg": "ECU 1 reported online."}
get2: {"type": "can", "msg": "ECU 2 reported online."}
The push is going to the queue object and the get is receiving them. In the browser's javascript console I see only two are received:
From everything I've read, the connection is established and there isn't any kind of "check" to make sure it's ready for sending and receiving.
However, if I put an arbitrary:
await asyncio.sleep(1)
at the beginning of the send()
function this seems to result in all the messages being sent. But that's a terrible solution and waiting for 1 second on every page reload/navigation is dumb.
Is there some other way I can approach this to get all the messages on a reload/navigation change?