从 axios / Promise 到 Dio / Future:一次讲透 Flutter 的异步与并发模型
本文澄清了异步编程中的关键概念:Dio和axios本质都是基于Future/Promise模型的HTTP客户端,两者可互相迁移。核心指出async/await不等于并发,await仅实现函数内部串行执行而不阻塞线程,真正并发来自同时创建多个Future。文章对比了前端和Flutter在拦截器设计、并发处理(Promise.all/Future.wait)及错误处理上的异同,强调这是可迁移的通用能力
前言
很多人学 Dio、async/await,会卡在几个问题上:
-
async / await到底是不是异步? -
为什么
await写多了感觉变慢了? -
并发到底是怎么来的?
-
前端 axios 和 Flutter Dio 是不是一套东西?
本文不讲“怎么调接口”,而是把模型讲清楚。
一旦理解这个模型,前端 / Flutter / 后端异步代码会全部打通。
一、Dio / axios 本质是什么?
一句话:
Dio(Flutter)≈ axios(前端)
它们都只是:
-
一个 HTTP 客户端
-
基于异步模型(Future / Promise)
-
支持拦截器(请求 / 响应 / 错误)
你学会其中一个,另一个几乎是零成本迁移。
二、Future ≈ Promise(这是根)
| 前端 | Flutter |
|---|---|
| Promise | Future |
| then / catch | then / catchError |
| async / await | async / await |
| Promise.all | Future.wait |
Future / Promise 的核心语义只有一句话:
现在没有结果,未来会有一个结果。
三、async / await 到底干了什么?
这是最容易被误解的地方。
结论先行(很重要)
async≠ 并发 ≠ 开线程async只做两件事:
允许你使用
await把返回值包装成
Future
await 的准确语义(不会错版本)
final result = await future;
含义是:
在“当前函数”里,
等这个 Future 完成后,
再执行下一行代码。
⚠️ 注意:
-
它只影响当前函数
-
不会阻塞 UI 线程
-
不会影响其他任务执行
四、为什么 await 看起来是“串行”?
因为在函数内部视角,它确实是串行的:
await A();
await B();
语义就是:
B 一定在 A 完成之后才执行
✔️ 串行
❌ 但不是阻塞线程
五、并发的真正来源(最核心结论)
❌ 错误理解
并发是 async / await 带来的
✅ 正确理解(定锚句)
并发来自“同时创建多个 Future / Promise”
串行写法(边创建边等)
await loadUser();
await loadOrder();
并发写法(先创建,再 await)
final userFuture = loadUser();
final orderFuture = loadOrder();
final user = await userFuture;
final order = await orderFuture;
标准并发写法(推荐)
final results = await Future.wait([
loadUser(),
loadOrder(),
]);
前端完全等价:
await Promise.all([
fetchUser(),
fetchOrder(),
]);
六、Dio / axios 拦截器:其实是一回事
前端 axios
-
请求拦截器
-
响应拦截器(成功 / 失败)
Flutter Dio
-
onRequest
-
onResponse
-
onError
本质模型完全一致,只是 Dio 把“错误”单独拆出来了。
七、为什么前端没有“错误拦截器”这个名字?
因为 axios 是这样定义的:
axios.interceptors.response.use(
successHandler,
errorHandler
);
👉 第二个参数本身就是“错误拦截器”
只是前端习惯把它归类在“响应拦截器”里。
八、并发 + 部分成功(工程常用)
前端
const results = await Promise.allSettled([
apiA(),
apiB(),
apiC(),
]);
Flutter
await Future.wait([
apiA().catchError((_) => null),
apiB().catchError((_) => null),
apiC().catchError((_) => null),
]);
思想完全一致:
不要让一个接口失败拖垮整个页面
九、关于“解构”的现实建议(很重要)
-
JS 解构(
const [a, b] = ...)是语言强项 -
Dart 更强调 清晰、显式、可维护
所以在 Flutter 项目里:
final res = await Future.wait([...]);
final a = res[0];
final b = res[1];
👉 这是完全正确、被广泛接受的工程写法
不需要强行“JS 化”。
十、最终总结
你现在已经真正理解了:
-
Promise ≈ Future
-
axios ≈ Dio
-
async / await ≠ 并发
-
await = 当前函数内的串行点
-
并发 = 同时创建多个任务
-
拦截器模型是跨端统一的
这是一套“可迁移的能力”,不是某个框架的死知识。
下一篇:
更多推荐



所有评论(0)