2026年5月30日 01:39
MobX 异步操作为什么要用 runInAction 或 flow?
MobX 处理异步的关键不是“能不能 await”,而是 await 之后的状态修改已经离开原来的 action。开启 enforceActions 时,接口返回后直接改 observable 容易报警,也会让更新边界不清。常用做法有两种:简单请求用 async/await + runInAction,在成功、失败分支里集中更新 data/loading/error;流程复杂、需要取消任务时用 flow(function*(){}),把 await 换成 yield。不要说 async action 会自动包住整个异步过程,它只覆盖同步阶段。
追问
runInAction 和 flow 怎么选?
普通接口请求选 runInAction,写法接近日常 async/await;多步骤流程、需要取消、想少写包装代码时选 flow。
为什么 await 后还要重新进 action?
因为 await 后是新的 tick,原 action 已结束。MobX 官方也强调 await 后的状态修改不在同一个执行阶段。
loading 和 error 应该怎么写?
进入请求前设 loading=true、清空 error;成功和失败分支都要把 loading=false 放进 action,避免页面一直转圈。
实际项目最常见的坑是什么?
最常见是 catch 里只记录错误,忘了重置 loading;其次是连续修改多个字段却没用 runInAction,导致严格模式报警。
写段代码
javascriptasync fetchUser(id) { this.loading = true this.error = null try { const data = await api.getUser(id) runInAction(() => { this.user = data; this.loading = false }) } catch (e) { runInAction(() => { this.error = e.message; this.loading = false }) } }