如何正确使用 await 与 toast.promise 配合异步请求

10次阅读

如何正确使用 await 与 toast.promise 配合异步请求

react 中调用异步登录函数时,若错误地对已 `await` 的结果再次传入 `toast.promise()`,会导致 toast 加载状态卡住——因为 `toast.promise` 必须接收一个 **promise 实例**,而非已解析的值。

toast.promise(promise, options) 是一个专为处理 Promise 状态(pending / fulfilled / rejected)而设计的工具方法。它内部会监听传入 Promise 的生命周期,并自动切换 loading、success 和 Error 提示。但前提是:你必须传入一个未被 await 或 .then() 消费过的原始 Promise 对象

来看你原始代码的问题所在:

onSubmit: async (values) => {   let loginPromise = await verifyPassword({ /* ... */ }); // ❌ 错误:这里已 await,loginPromise 是 resolved 值(如 { data: {...} }),不再是 Promise!    toast.promise(loginPromise, { /* ... */ }); // ⚠️ 传入的是普通对象 → toast 无法监听状态 → loading 一直显示    loginPromise.then((res) => { /* ... */ }); // ❌ loginPromise 已不是 Promise,.then 无效(静默失败) },

✅ 正确做法是:保留 verifyPassword(…) 返回的 Promise,直接传给 toast.promise,再 await 它的返回值(即最终响应)。toast.promise 本身会返回你传入的同一个 Promise(经包装增强),因此可链式 await 获取结果:

onSubmit: async (values) => {   // ✅ 正确:loginPromise 是 Promise 实例   const loginPromise = verifyPassword({     username,     password: values.password,   });    // ✅ toast.promise 接收 Promise,并返回它(支持 await)   const res = await toast.promise(loginPromise, {     loading: "Checking...",     success: Login successfully...,     error: Incorrect Password,   });    // ✅ 此时 res 即 verifyPassword resolve 的值(如 { data: { token } })   const { token } = res.data;   localStorage.setItem("token", token);   navigate("/profile"); },

⚠️ 补充注意事项:

  • 不要混用 await 和 .then() 处理同一 Promise(易引发竞态或重复执行);
  • verifyPassword 内部已 await axios.post(…),外部无需再 await 两次;
  • 若需全局错误兜底(如网络异常未被捕获),可在 toast.promise 外层加 try/catch,但通常 toast.error 已覆盖业务错误;
  • verifyOTP 示例能正常工作,正是因为 await verifyOTP(…) 是直接等待结果并手动处理,未涉及 toast.promise —— 二者适用场景不同:toast.promise 用于「需要 ui 反馈 Promise 状态」,纯 await 适用于「仅需结果、自行控制提示」。

总结:await 用于获取 Promise 结果;toast.promise 用于将 Promise 的状态映射到 UI。二者目标不同,不可替代,更不可叠加滥用。 记住口诀:“传 Promise 给 toast,用 await 拿结果”

text=ZqhQzanResources