这是一个非常棒的问题!JavaScript 中的 Promise 是异步编程的核心,而 Python 虽然语法不同,但也有非常相似且更强大的机制来实现同样的功能。
🎯 目标
我们要在 Python 中实现类似 JavaScript Promise 的能力:
// JavaScript Promise 示例
fetch('/api/data')
.then(data => process(data))
.catch(err => console.error(err))
.finally(() => console.log('完成'))
✅ 答案:Python 中的 async/await + asyncio 就是 Promise 的“升级版”
| JavaScript | Python |
|---|---|
Promise | asyncio.Future / Task |
.then() | await |
.catch() | try/except |
Promise.all() | asyncio.gather() |
async/await | async/await(语法几乎一样) |
🔥 所以:Python 的
async/await就是 Promise 的“现代、原生”实现
🧱 一、JavaScript Promise vs Python 协程(async/await)
✅ JavaScript:Promise 风格
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function main() {
console.log("开始");
await delay(1000);
console.log("1秒后");
}
main();
✅ Python:async/await 风格
import asyncio
async def delay(ms):
await asyncio.sleep(ms / 1000) # asyncio.sleep 接受秒
async def main():
print("开始")
await delay(1000)
print("1秒后")
# 运行异步函数
asyncio.run(main())
✅ 输出完全一样!
🧩 二、Python 中的 “Promise” 是什么?
Python 中没有叫 Promise 的类,但有:
1. asyncio.Future → 相当于 new Promise()
- 表示一个“将来会完成”的结果
- 可以手动
set_result()或set_exception()
import asyncio
async def create_promise():
future = asyncio.Future()
# 模拟异步操作(比如 1 秒后 resolve)
async def resolver():
await asyncio.sleep(1)
future.set_result("Promise 已完成!")
# 启动解析器
asyncio.create_task(resolver())
# 等待结果(相当于 .then)
result = await future
print(result)
asyncio.run(create_promise())
输出:
Promise 已完成!
🔗 三、.then() 和 .catch() 怎么实现?
Python 没有 .then(),但可以用:
✅ 方式1:await + try/except(推荐)
async def fetch_data():
await asyncio.sleep(0.5)
if False: # 模拟失败
raise Exception("网络错误")
return {"id": 1, "name": "小明"}
async def main():
try:
data = await fetch_data()
print("✅ 数据:", data) # 相当于 .then()
except Exception as e:
print("❌ 错误:", e) # 相当于 .catch()
finally:
print("🎉 完成") # 相当于 .finally()
asyncio.run(main())
🔄 四、Promise.all() 怎么实现?
JavaScript:
Promise.all([p1, p2, p3]).then(results => ...)
Python:
import asyncio
async def task1(): await asyncio.sleep(1); return "结果1"
async def task2(): await asyncio.sleep(2); return "结果2"
async def task3(): await asyncio.sleep(1); return "结果3"
async def main():
# 相当于 Promise.all()
results = await asyncio.gather(
task1(),
task2(),
task3()
)
print(results) # ['结果1', '结果2', '结果3']
asyncio.run(main())
✅ 并发执行,等待所有完成
⏳ 五、Promise.race() 怎么实现?
JavaScript:哪个 Promise 先完成就用哪个
Python:
async def slow(): await asyncio.sleep(2); return "慢"
async def fast(): await asyncio.sleep(1); return "快"
async def main():
result = await asyncio.wait(
[slow(), fast()],
return_when=asyncio.FIRST_COMPLETED
)
done, pending = result
print("最先完成:", done.pop().result()) # 快
asyncio.run(main())
📦 六、封装一个类 Promise 的工具(可选)
如果你真的想要 .then().catch() 风格,可以封装:
class Promise:
def __init__(self, coro):
self.task = asyncio.create_task(coro)
def then(self, success):
async def wrapper():
try:
result = await self.task
return success(result)
except Exception as e:
return self._error or (lambda err: None)(e)
return Promise(wrapper())
def catch(self, failure):
self._error = failure
return self
# 使用示例
async def get_data():
await asyncio.sleep(1)
return "Hello"
def on_success(data):
print("成功:", data)
def on_error(err):
print("失败:", err)
# Promise 风格调用
Promise(get_data()).then(on_success).catch(on_error)
# 但需要运行事件循环
asyncio.run(asyncio.sleep(2)) # 等待完成
💡 但这不是 Python 风格,推荐直接用
async/await
✅ 七、Python vs JavaScript 异步对比总结
| 功能 | JavaScript | Python |
|---|---|---|
| 定义异步函数 | async function fn() | async def fn(): |
| 等待异步结果 | await promise | await coro |
| 错误处理 | .catch() 或 try/catch | try/except |
| 并发多个任务 | Promise.all() | asyncio.gather() |
| 竞速 | Promise.race() | asyncio.wait(..., FIRST_COMPLETED) |
| 创建“Promise” | new Promise() | asyncio.Future() |
| 运行事件循环 | 浏览器自动 | asyncio.run() |
🎯 八、最佳实践:Python 中如何“正确”使用 Promise 思维
- ✅ 使用
async/await写异步代码 - ✅ 用
asyncio.gather()并发请求 - ✅ 用
try/except处理错误 - ✅ 不要手动封装
.then(),那是 JS 的风格 - ✅ 所有异步入口用
asyncio.run()
🚀 九、实战示例:并发获取多个 API 数据
import asyncio
import aiohttp # 需要安装: pip install aiohttp
async def fetch(session, url):
async with session.get(url) as res:
return await res.json()
async def main():
urls = [
'https://jsonplaceholder.typicode.com/posts/1',
'https://jsonplaceholder.typicode.com/posts/2',
'https://jsonplaceholder.typicode.com/posts/3',
]
async with aiohttp.ClientSession() as session:
try:
results = await asyncio.gather(
*[fetch(session, url) for url in urls],
return_exceptions=True # 某个失败不影响其他
)
for i, r in enumerate(results):
if isinstance(r, Exception):
print(f"请求 {i+1} 失败: {r}")
else:
print(f"请求 {i+1} 成功: {r['title']}")
except Exception as e:
print("批量请求失败:", e)
asyncio.run(main())
✅ 这就是 Python 中的“Promise.all()”最佳实践!
✅ 总结
| 问 | 答 |
|---|---|
| Python 有 Promise 吗? | 没有叫 Promise 的类,但有更强大的 async/await |
怎么实现 .then().catch()? | 用 await + try/except |
Promise.all() 对应什么? | asyncio.gather() |
| 推荐写法? | 直接用 async/await,不要模仿 JS 风格 |
🎯 记住:Python 的
async/await不是模仿 Promise,而是它的“进化版”