async for是python异步迭代核心语法,用于流式处理分页数据、websocket消息等需按需拉取并逐条处理的异步数据源,依赖__aiter__和__anext__协议实现非阻塞迭代。

直接把传统 for 循环改成流式迭代,关键不是重写逻辑,而是把“一次性拉取+全量处理”变成“按需拉取+逐条处理”。异步生成器(async function*)正是这个转换的桥梁——它让循环体变成可暂停、可等待、可 yield 的数据源。
识别适合改写的循环模式
以下几类传统循环最值得优先改造:
- 分页请求:比如
for (let page = 1; page - 文件/流读取:如 Node.js 中用
fs.createReadStream分块读,再手动拼接处理 - 实时消息监听:通过
socket.addEventListener('message', ...)回调不断接收数据 - 数据库游标遍历:执行查询后逐行 fetch,但当前用 while + callback 或 Promise 链管理
三步完成改写:封装 → 替换 → 消费
以分页 API 为例,原写法是同步控制流,但实际每页请求都是异步的。改写不改变业务意图,只改变执行节奏:
-
封装为异步生成器:把循环逻辑移入
async function*,用yield输出每批结果async function* fetchAllPages() {<br> let page = 1;<br> while (true) {<br> const res = await fetch(`/api/items?page=${page}`);<br> const items = await res.json();<br> if (items.length === 0) break;<br> yield items;<br> page++;<br> }<br>} - 替换原循环调用:不再手动管理 page 变量和终止条件,也不再收集到一个大数组里
-
用
for await...of消费:语法几乎一致,但语义已变为流式for await (const items of fetchAllPages()) {<br> console.log(`Processing ${items.length} items`);<br> processBatch(items);<br>}
保持原有逻辑完整性
改写不是推倒重来,而是增强可控性。你仍可做这些事:
-
提前退出:在
for await内部用break或return,生成器会自动清理(配合try/finally更稳妥) -
错误传播:生成器内
await报错会直接抛出,for await外可用try/catch捕获 -
中间处理:可在生成器内部对每条数据做轻量转换或过滤,例如
if (item.status === 'active') yield item; -
资源清理:WebSocket 或文件句柄等,放在生成器的
finally块中关闭,确保连接中断时释放
避免常见误区
改写容易,但几个细节决定是否真正“无缝”:
- 不要在生成器外用
Promise.all批量触发所有请求——那又变回了全量加载,失去流式意义 - 不要把同步生成器(
function*)直接传给for await,会报错“not async iterable” - 若原循环依赖全局状态(如累加器),需评估是否应移到消费者侧;生成器本身应尽量无副作用、可复用
- 注意浏览器兼容性:
async function*和for await需要现代环境(Chrome 63+/Firefox 57+),Node.js 10.0+ 支持










