进阶:客户端结果与取消
客户端结果
服务器可以调用单个客户端的方法并等待其返回值。客户端必须为该方法注册
处理器;处理器返回的非 None 值作为结果回发。
class EchoHub(Hub):
async def ping_client(self) -> str:
return await self.clients.caller.invoke("client_method", "hello-from-server")
客户端侧:
async def client_method(text: str) -> str:
return f"ack:{text}"
connection.on("client_method", client_method)
result = await connection.invoke("ping_client")
print(result) # "ack:hello-from-server"
invoke(method, *args)返回客户端结果;客户端返回错误时抛HubException。- 可选
timeout参数:客户端未在时限内应答时抛SignalRError。 - 客户端结果按连接用服务器生成的调用 id(
s1、s2…)跟踪。
工作原理
- 服务器为新的调用 id 注册一个 future。
- 向客户端发送带该调用 id 的
Invocation消息。 - 客户端运行处理器,回复携带返回值(或错误)的
Completion。 - 服务器解析 future。
取消
客户端可以用 CancelInvocation 取消在途调用。服务器以两种方式响应:
- 置位该调用的
cancellation_token(一个asyncio.Event)。 - 取消运行 hub 方法的底层任务。
class ProbeHub(Hub):
async def cancelable(self, n: int, cancellation_token: Any = None) -> int:
try:
for i in range(n):
await asyncio.sleep(0.05)
if cancellation_token is not None and cancellation_token.is_set():
return i
return n
except asyncio.CancelledError:
return -1
aiosignalr 客户端在 stream() 迭代器被提前放弃时自动发送 CancelInvocation。
并行调用
默认每条连接一次处理一个调用(maximum_parallel_invocations = 1),与参考
服务器一致。调高可让单条连接并发运行多个 hub 方法:
server = SignalRServer(MyHub, options=ServerOptions(maximum_parallel_invocations=4))
流式方法始终在独立任务上启动,因此流式期间不会占用调用信号量。