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;
    }
}
相关推荐
phltxy15 分钟前
Vue 核心特性实战指南:指令、样式绑定、计算属性与侦听器
前端·javascript·vue.js
Byron07071 小时前
Vue 中使用 Tiptap 富文本编辑器的完整指南
前端·javascript·vue.js
css趣多多1 小时前
地图快速上手
前端
zhengfei6112 小时前
面向攻击性安全专业人员的一体化浏览器扩展程序[特殊字符]
前端·chrome·safari
码丁_1172 小时前
为什么前端需要做优化?
前端
Mr Xu_2 小时前
告别硬编码:前端项目中配置驱动的实战优化指南
前端·javascript·数据结构
Byron07073 小时前
从 0 到 1 搭建 Vue 前端工程化体系:提效、提质、降本实战落地
前端·javascript·vue.js
哆啦code梦3 小时前
前端存储三剑客:localStorage、sessionStorage与Cookie解析
前端·前端存储
徐小夕@趣谈前端3 小时前
Web文档的“Office时刻“:jitword共建版2.0发布!让浏览器变成本地生产力
前端·数据结构·vue.js·算法·开源·编辑器·es6
Data_Journal3 小时前
如何使用 Python 解析 JSON 数据
大数据·开发语言·前端·数据库·人工智能·php