用 async 函数封装复杂 ui 交互流程,核心是把“用户触发—状态切换—异步操作—反馈更新—错误兜底”收束为可 await、可组合、可复用的逻辑单元,聚焦校验与 api 等真正异步节点,通过回调或返回值暴露控制权,抛出 validationerror、networkerror、businesserror 等结构化错误,不侵入 ui 状态管理。

聚焦交互主干,拆出关键异步节点
UI 交互常含多个等待点:比如点击提交按钮后,要校验表单 → 调用 API → 显示成功提示 → 跳转页面 → 清空字段。其中只有校验和 API 是真正异步的,其余是同步副作用。async 封装应只包裹真正需等待的部分:• 表单校验(返回 Promise
• 主要业务请求(如 api.submitOrder(data))
• 关键副作用(如 router.push() 返回 Promise,或 notification.success() 支持 await)
• 避免把 setState、log、隐藏 loading 这类同步操作也塞进 async 函数里——它们该由调用方按需处理
统一管理中间态与副作用
async 函数本身不直接操作 UI 状态,但可通过参数或返回值暴露控制权:• 接收 { onStart, onSuccess, onError, onFinally } 回调,让调用方决定 loading 怎么开、提示怎么显
• 返回一个包含状态的对象,例如 { data, error, isLoading },供 computed 或 useEffect 消费
• 对需要取消的场景(如搜索框防抖+中途取消),接受 AbortSignal 作为选项,并在 fetch 中透传
支持结构化错误与业务语义
不要让调用方自己解析 error.message。封装层应提前分类并抛出带语义的错误实例:• ValidationError:表单校验失败,附带字段名和消息
• NetworkError:fetch 抛异常或超时,保留原 response 和 status
• BusinessError:API 返回 code !== 200,提取 message 和 errorCode 字段
• 调用方可用 try/catch 按类型分别处理:catch (e: ValidationError) { showFieldError(e.field) }
保持轻量,避免侵入式状态绑定
async 函数不是 Store,也不该接管组件的 ref 或 useState:• 不在函数内部调用 setLoading(true)
• 不自动调用 message.success()
• 不修改传入的 formRef.current
• 它只做一件事:执行异步逻辑 + 返回结果或抛出错误
• UI 反馈、状态更新、导航跳转,全部交给外部协调 —— 这样才能跨 Vue/React 複用,也便于单元测试











