Skip to content

异步

类型会标了,看异步怎么跑。先入口,再迭代,再并发。

async / await / asyncio.run

python
async def async_main() -> None:
    await execution.async_start(payload)
    await execution.async_close()

def main() -> None:
    asyncio.run(async_main())
js
async function asyncMain() {
  await execution.asyncStart(payload)
  await execution.asyncClose()
}

await asyncMain()

Python 文件顶层一般不能直接 await,要用 asyncio.run(...) 包一层。Node 顶层可以 await

默认参数也可以塞异步函数引用:

python
async def run(extractor: SegmentExtractor = extract_segment_from_reference):
    ...
js
async function run(extractor = extractSegmentFromReference) {
  ...
}

async for

python
async for item in result.get_async_generator(type="instant"):
    if not item.is_complete:
        continue
    await emit_action_ready(...)
js
for await (const item of asyncGenerator) {
  if (!item.is_complete) continue
  await emitActionReady(...)
}
PythonJavaScript
async for x in agen:for await (const x of agen)
asyncio.sleep(秒)setTimeout 包成 Promise(毫秒)
python
await asyncio.sleep(0.01)
js
await new Promise((r) => setTimeout(r, 10))

create_task:先跑、稍后再等

python
close_task = asyncio.create_task(execution.async_close())
async for item in execution.get_async_runtime_stream(timeout=None):
    items.append(item)
state = await close_task
js
const closePromise = execution.asyncClose()
for await (const item of execution.getAsyncRuntimeStream()) {
  items.push(item)
}
const state = await closePromise

模式:关执行和读流重叠进行。create_task(coro) ≈ 先拿到 Promise,稍后再 await

gather:一起等完

asyncio.gather(*tasks) 把一堆协程同时跑,全部结束后才往下。* 把列表拆开传进去。

python
tasks = [_run(item) for item in items]
await asyncio.gather(*tasks)
js
const tasks = items.map((item) => run(item))
await Promise.all(tasks)
PythonJavaScript
asyncio.gather(*tasks)Promise.all(tasks)
默认一个失败就取消其余Promise.all 同样:一个 reject 就整组失败

只要「谁先好谁先用」用 create_task;要「这批全好再继续」用 gather

async with + Semaphore

async with 是异步版 with:进入时获取,离开时释放。常和 Semaphore 限并发。

python
semaphore = asyncio.Semaphore(bounded)

async def _run(item):
    async with semaphore:
        by_id[item.item_id] = await summarize(item)

await asyncio.gather(*[_run(item) for item in items])
js
await Promise.all(
  items.map(async (item) => {
    await limit.acquire()
    try {
      byId[item.item_id] = await summarize(item)
    } finally {
      limit.release()
    }
  }),
)

JS 没有 async with。对等写法是 try/finally 里释放;限流要自己数,或用现成池(如 p-limit)。

yield:异步生成器

async defyield 就变成异步生成器,外面用 async for 逐个拿。

python
async def iter_messages(queue):
    try:
        while True:
            yield await queue.get()
    finally:
        cleanup()
js
async function* iterMessages(queue) {
  try {
    while (true) {
      yield await queue.get()
    }
  } finally {
    cleanup()
  }
}
PythonJavaScript
async def + yieldasync function* + yield
外面 async for x in agenfor await (const x of agen)
调用方 break / aclose()迭代器 return(),会走 finally

同步版是普通 def + yield,外面用普通 for。这里课程里常见的是异步那条。

下一页是最后一层:闭包工厂、装饰器、命令行、图状态类型。