umi踩坑记录 —— useRequest 以及 umi 请求报错捕获流程

引言

我们的项目中使用了 useRequest 这个 hooks。今天下午我在写项目的过程中发现,假如我的登录密码是错误的,当后端成功返回异常信息后,页面就报错了,提示我异常没有被成功捕获(Unhandled Rejection)......因为这个问题折腾了好几个小时

原因

先说一下原因吧,因为目前 Umi 4 中内置的 ahooks 版本为 2.x 版本,2.x 版本中的 useRequest 并没有返回 runAsync,即异步请求函数。但是在某些场景中,我希望通过异步请求来实现某些功能,又不想在项目中使用两种请求方案,即 useRequest 和直接使用 services 封装的请求函数

于是,我安装了 ahooks 3.x。在需要使用异步请求的地方,引用了 ahooks 3.x 中的 useRequest 函数,登录请求便在其中~

解决方案

解决方案为:为登录请求相关的 useRequest 及所有异步请求的函数都加了 try ... catch

总结

runAsync 返回的异步函数中,想要捕获错误使用自带的 onError 函数和 errorHandle 函数是处理不了的,如果该异步函数抛出了异常,上述的函数再处理完成后还会抛给外部一个异常,所以最后的解决方法必须要在最外层加一个 try ... catch

既然谈到这里了,也都走了一遍坑,我就总结一下 umi 全局请求是怎么捕获错误的

umi 全局请求的错误是怎么捕获的

在 umi 项目中,我们优先使用 umi 插件自带的 request,首先需要在 .umirc.ts 文件中增加配置

tsx 复制代码
export default defineConfig({
  request: {},
});

在定义请求时,引用 umi 中的请求,我使用的是 umi/max

ts 复制代码
import { BASE_URL } from './config.ts';
import { request } from '@umijs/max';

export const requestUserLogin = async (data: any) => {
    return await request(`${BASE_URL}/api/user/login`, {
    method: 'post',
    data,
  });
}

我们通常需要对后端传回的数据进行全局处理,比如后端虽然成功响应,但是在返回的 data 中 code 不为 200 或者 success,我们就需要在 app.tsx 中进行配置

ts 复制代码
// app.tsx
import type { RequestConfig } from '@umijs/max';

export const request: RequestConfig {
    timeout: 1000 * 6,
    errorConfig: {
        errorThrower: (res) => {
            // 后端返回数据后,都会执行此函数,如果不符合条件,我们可以手动抛出一些错误,从而会被 errorHandle 捕获
            
            // 此处的 res 为响应拦截器中的 res.data 部分,为后端自己手动封装的 body 部分
            const { code, message } = res;
            if (code !== 200) {
                const error: any = new Error(message);
                error.name = 'BizError';
                error.info = { message, code };
                throw error; // 抛出自制的错误
            },
        },
        // 此函数只能对 useRequest 中 run 返回的同步函数内部的异步函数进行错误捕获;如果为 runAsync 或者我们自定义的异步请求函数,并且该错误是由 errorThrower、 responseInterceptors 或者 requestInterceptors 抛出(即不是请求的 status 不为 200),在 errorHandle 执行完之后还会抛出一个错误,所以异步请求一定要记得加 try ... catch
        errorHandle: (error) => {
            // 分情况处理错误
            // 错误可能为我们手动抛出的错误,可能为状态码(status)不为 200 的错误,或者后端服务没有响应的错误,或者是发送请求时出现的其它错误等等
            if (error.name === 'BizError') {
                // switch ...
            } else if (error.response?.status) {
                // 请求已发送,并且收到了响应,但是状态码超出了 2xx 的范围
                // 分情况处理
                // switch (error.response.status) {}
            } else if (error.request) {
                // 请求已发送,但是没有收到响应
            } else {
                // 发送请求前出现了问题
            }
        }
    },
    // 请求拦截
    requestInterceptors: () => {},
    // 响应拦截
    responseInterceptors: (res) => {
        // 此处抛出的错误会直接进入errorHandle,但我们一般选择在errorThrower中抛出
        
        // 此处的 res 包含整个响应内容,包括headers、status、data、config等等
        return res;
    }
}
相关推荐
kyriewen1 小时前
你的前端滤镜慢得像PPT?用Rust+WebAssembly,一秒处理4K图
前端·rust·webassembly
kyriewen111 小时前
你等的Babel编译,够喝三杯咖啡了——用Rust重写的SWC,只需眨个眼
开发语言·前端·javascript·后端·性能优化·rust·前端框架
IT_陈寒2 小时前
SpringBoot自动配置坑了我,原来要这样绕过去
前端·人工智能·后端
东方小月2 小时前
Claude Code 完整上手指南:MCP、Skills、第三方模型配置一次搞定
前端·人工智能·后端
XZ探长2 小时前
基于 Trae Solo 移动办公修复 Vue3 前端服务问题
前端
小程故事多_802 小时前
[大模型面试系列] 深度解析ReAct框架,大模型Agent的“思考+行动”底层逻辑
人工智能·react.js·面试·职场和发展·智能体
蝎子莱莱爱打怪3 小时前
Claude Code 省 Token 小妙招:RTK + Caveman 组合拳
前端·人工智能·后端
Momo__3 小时前
Vue 3.6 Vapor Mode:跳过虚拟 DOM,性能极致优化
前端·vue.js
少年白马醉春风丶3 小时前
从零构建 AIGC 无限画布:AIGCCanvasFlow 技术全解析
前端·后端·aigc
OpenTiny社区3 小时前
生成式 UI 藏大招!看似露营案例,实则电商集成 GenUI SDK 干货
前端·ai编程·交互设计