异步编程中的 Future

34 阅读2分钟

Future 类

asyncio.Future 是异步编程里的核心概念:代表一个异步操作的最终结果,本质上是一个**「结果占位符」**。

可以把它理解成异步世界里的**「欠条」**——现在还没结果,但将来某个时刻会有。

一句话:Future 就是一张**「取餐号」**:你拿到它时结果还没有,但你可以 await 它,等结果好了自动拿到。


用生活场景理解

想象你去奶茶店点了一杯奶茶:

  1. 付完钱,店员给你一个取餐号(这就是 Future)
  2. 奶茶还没做好,但你知道「迟早会做好」
  3. 你可以选择:
    • 等着await future)—— 站在柜台前等,做好了直接拿走
    • 先干别的add_done_callback)—— 去逛街,做好了店员打电话通知你

这个「取餐号」就是 Future 的本质——一个将来才会有结果的承诺。


最简单的例子

import asyncio

async def main():
    # 1. 创建一张"欠条"
    future = asyncio.get_running_loop().create_future()

    # 2. 1秒后把结果填上去
    asyncio.get_running_loop().call_later(1, future.set_result, "奶茶好了!")

    # 3. 等着拿结果
    result = await future
    print(result)  # 输出: 奶茶好了!

asyncio.run(main())

整个过程就是:

  1. 创建一张空白的「欠条」(Future)
  2. 某个时刻,有人把结果写上去(set_result
  3. await 就是「等结果写好再往下走」

那它到底有什么用?

最典型的场景:你在写一个库,需要让调用者等待某个异步操作完成。

比如连接数据库:底层是回调风格,对外却想让人用 await

import asyncio


# 模拟底层数据库连接库
# 它不是 async 函数,而是传统的回调风格
def some_low_level_connect(host: str, callback):
    print(f"[底层库] 开始连接 {host} ...")

    def on_connected():
        # 模拟连接成功后,返回一个 connection 对象
        connection = {"host": host, "status": "connected"}
        callback(connection)

    # 模拟网络延迟:1 秒后调用 callback
    asyncio.get_running_loop().call_later(1, on_connected)


async def connect_db(host: str = "127.0.0.1:5432"):
    # 1. 创建一张“欠条”
    future = asyncio.get_running_loop().create_future()

    # 2. 调用底层回调式接口,把 future.set_result 当作回调传进去
    #    等底层连接成功后,会自动执行:future.set_result(connection)
    some_low_level_connect(host, callback=future.set_result)

    # 3. 调用者只需要 await,就能拿到最终结果
    connection = await future
    return connection


async def main():
    print("准备连接数据库...")

    connection = await connect_db("127.0.0.1:5432")

    print("连接成功,拿到结果:")
    print(connection)


asyncio.run(main())

Future 把「回调拿到结果」和「await 拿到结果」接在一起。


三种状态

Future 有且仅有三种状态:

状态含义
Pending(未完成)初始状态,操作还在进行中
Done(已完成)操作已结束(成功设了结果,或设了异常)
Cancelled(已取消)被显式取消

核心 API

方法作用
set_result(value)设置结果,状态变为 Done
set_exception(exc)设置异常,状态变为 Done
result()获取结果(未完成时抛 InvalidStateError
done()是否已完成
cancelled()是否已取消
cancel()取消 Future
add_done_callback(cb)注册完成回调
get_loop()获取绑定的事件循环