目前可以通过提供将在每个传入连接上触发的回调来启动asyncio服务器:
async for
我想摆脱回调并改用async for reader, writer in my_start_server(host, port):
# this should be invoked each time a new connection is made
pass
,所以看起来像这样:
async def my_start_server(host, port):
async def on_connection(reader, writer):
# here I have to somehow yield (reader, writer) tuple
# but if I do just `yield (reader, writer)`, it would
# make `on_connection` itself a generator, but would
# not affect `my_start_server`
pass
server = await asyncio.start_server(on_connection, host, port)
不幸的是,它似乎并不容易:
__aiter__
我曾考虑过在那里实现Auth::guard('api')->user()
实现的类,但结果似乎过于复杂。那么,这是唯一的方法,还是我错过了将异步回调转换为异步生成器的任何简单方法?
答案 0 :(得分:1)
正如文森特所注意到的那样,你不应该使用async for
来获取连接,因为它内部的代码会阻止其他连接处理。将每个连接视为应该运行的单独任务,而不管其他任何连接。
以下示例yield
如何使用my_start_server
使用队列,这也表明我们仍会返回某种on_connection
:
async def my_start_server(host, port):
queue = asyncio.Queue()
async def put(reader, writer):
await queue.put((reader, writer,))
await asyncio.start_server(put, host, port)
while True:
yield (await queue.get())
async for (reader, writer) in my_start_server(host, port):
# If we will just handle reader/writer here, others will be suspended from handling.
# We can avoid it starting some task,
# but in this case 'handle' would be nothing different from 'on_connection'
asyncio.Task(handle(reader, writer))