Skip to content

Commit 09c8b08

Browse files
Introduce _waiting_for_connection event for more efficient page function (#4466)
@evnchn After thinking about PRs #4461 and #4462, I came up with another idea how we can wait for async page functions more efficiently. By introducing a new "waiting for connection" event, we can simultaneously wait for both: 1. our task waiting for the page function to return 2. the new event which occurs when the page function calls `await client.connected()`. Furthermore, we can specify a timeout very easily. @evnchn What do you think? Does that solve our problem?
1 parent 729e714 commit 09c8b08

File tree

2 files changed

+9
-6
lines changed

2 files changed

+9
-6
lines changed

nicegui/client.py

+2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ def __init__(self, page: page, *, request: Optional[Request]) -> None:
5656

5757
self.elements: Dict[int, Element] = {}
5858
self.next_element_id: int = 0
59+
self._waiting_for_connection: asyncio.Event = asyncio.Event()
5960
self.is_waiting_for_connection: bool = False
6061
self.is_waiting_for_disconnect: bool = False
6162
self.environ: Optional[Dict[str, Any]] = None
@@ -177,6 +178,7 @@ def resolve_title(self) -> str:
177178
async def connected(self, timeout: float = 3.0, check_interval: float = 0.1) -> None:
178179
"""Block execution until the client is connected."""
179180
self.is_waiting_for_connection = True
181+
self._waiting_for_connection.set()
180182
deadline = time.time() + timeout
181183
while not self.has_socket_connection:
182184
if time.time() > deadline:

nicegui/page.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import asyncio
44
import inspect
5-
import time
65
from functools import wraps
76
from pathlib import Path
87
from typing import TYPE_CHECKING, Any, Callable, Optional, Union
@@ -124,11 +123,13 @@ async def wait_for_result() -> None:
124123
with client:
125124
return await result
126125
task = background_tasks.create(wait_for_result())
127-
deadline = time.time() + self.response_timeout
128-
while task and not client.is_waiting_for_connection and not task.done():
129-
if time.time() > deadline:
130-
raise TimeoutError(f'Response not ready after {self.response_timeout} seconds')
131-
await asyncio.sleep(0.1)
126+
try:
127+
await asyncio.wait([
128+
task,
129+
asyncio.create_task(client._waiting_for_connection.wait()), # pylint: disable=protected-access
130+
], timeout=self.response_timeout, return_when=asyncio.FIRST_COMPLETED)
131+
except asyncio.TimeoutError as e:
132+
raise TimeoutError(f'Response not ready after {self.response_timeout} seconds') from e
132133
if task.done():
133134
result = task.result()
134135
else:

0 commit comments

Comments
 (0)