umi icon indicating copy to clipboard operation
umi copied to clipboard

umi@4 errorHandler 会继续抛出异常

Open tolerance-go opened this issue 1 year ago • 6 comments

What happens?

接口返回 504,定义了 errorHandler 会继续抛异常出来,我必须在 request 后手动 catch 住才行

Mini Showcase Repository(REQUIRED)

Please provide a minimal reproduction then upload to your GitHub. 请提供 最小重现,并上传到你的 GitHub 仓库

应该是这里的插件代码,但是这样设计 errorHandler 很不好用啊,可以通过 errorHandler 里面 return 来判断一下是否继续抛吗,现在需要封装一下 request 方法 image

How To Reproduce

Steps to reproduce the behavior: 1. 2.

Expected behavior 1. 2.

Context

  • Umi Version:
  • 4
  • Node Version:
  • 16.16.0
  • Platform:
  • macOS

tolerance-go avatar Jul 13 '22 13:07 tolerance-go

加2个注释帮助大家理解 image

如果希望前端能获取统一的数据格式请求返回,我这里分享一下封装(我没有用 useRequest) image

tolerance-go avatar Jul 13 '22 14:07 tolerance-go

umi3中request的错误处理逻辑不会影响最终传递给页面的数据格式,但现在得额外增加try catch才能保证程序继续执行下去

LanJamRom avatar Jul 15 '22 09:07 LanJamRom

确实存在这个问题,官方有没有统一处理的想法?

imoxuan avatar Jul 22 '22 07:07 imoxuan

多谢老哥,确实有问题,按你的先做了

ChrisLuckComes avatar Jul 29 '22 06:07 ChrisLuckComes

貌似 !200status 只能通过 try catch 来获取 🤔

jkiss avatar Aug 04 '22 07:08 jkiss

可以通过errorHandler里面的return 来判断一下是否继续抛吗 不抛错误的话,是想resolve还是代码停住呢?

July-ing avatar Aug 11 '22 03:08 July-ing

我现在用 ahooks@3 + axios 单独做请求了,暂时放弃 max 里面的 request 了

tolerance-go avatar Aug 23 '22 16:08 tolerance-go

继续 throw 是因为 useRequest 需要 reject 吧

tolerance-go avatar Aug 23 '22 17:08 tolerance-go

1、errorHandler只能处理httpstatus != 200 的请求 2、如果业务异常但httpstatus == 200的话 在responseInterceptors中处理 3、如果用useRequest的话,在app.ts中将useRequest的默认设置改成如下:

const RequestProvider = ({ children }: any) => {
  return <UseRequestProvider value={{throwOnError:true}}>{children}</UseRequestProvider>
}

export function rootContainer(container: any) {
  return React.createElement(RequestProvider, {}, container);
}

liuqiandev avatar Oct 31 '22 01:10 liuqiandev

这个算是breaking change了吧,umi3里面umi-request的errorHandler会自动捕获异常,不再传递异常给dva;但到了umi4,通过在app.ts中配置了request的errorHandler,异常会一直传递,导致dva执行中断。

我通过在app.ts配置解决了这个问题,要不然就得在dva里面每次call的时候都加一遍try catch

export const dva = {
  config: {
    onError(e: any) {
      e.preventDefault();
      console.error(e.message);
    },
  },
};

hank619 avatar Jul 13 '23 08:07 hank619

我现在用 ahooks@3 + axios 单独做请求了,暂时放弃 max 里面的 request 了

请问能分享下完整的代码么?

dialYun avatar Dec 23 '23 01:12 dialYun

我现在用 ahooks@3 + axios 单独做请求了,暂时放弃 max 里面的 request 了

请问能分享下完整的代码么?

app/request/index.ts

export const instance = axios.create({
  timeout: 10000,
  baseURL: baseHost(),
});


instance.interceptors.request.use(
  (config) => {
    Object.assign(config, { headers: getHeaders() });
    if (config.method === 'post') {
      Object.assign(config, { data: dataAssign(config.data, true) });
    }
    if (config.method === 'get') {
      Object.assign(config, { params: dataAssign(config.params, true) });
    }
    return { ...config };
  },
  (error) => {
    if (error.request) {
      showNotice(7, `请求错误`, `未接收到系统返回,请重试`);
    } else {
      showNotice(7, `系统错误`, `系统请求错误,请重试`);
    }
  },
);


instance.interceptors.response.use(
  (response) => {
    const { data = {} as any } = response;

    const {
      errorMessage = '系统异常,请稍后再试',
      errorCode,
      showType = 0,
    } = data;
    if (data.success === false) {
      let tips = '登录状态验证错误,请重新登录';
      if (errorCode <= -99900) {
        logout();
      } else {
        tips = `[${errorCode}]${errorMessage ?? '未返回错误信息'}`;
        showNotice(showType, `系统错误`, tips);
      }
      throw new Error(tips);
    } else {
      showNotice(showType, `系统提示`, errorMessage);
      return data;
    }
  },
  (error) => {
    let msg = '系统请求错误,请重试';
    if (error.response) {
      const { status } = error.response;
      msg = `系统响应错误,错误码:[${status}]`;
      showNotice(7, `响应错误`, msg);
    } else {
      showNotice(7, `系统错误`, msg);
    }
    const serverError = new Error(msg);
    serverError.name = 'ServerError';
    return Promise.reject(serverError);
  },
);


export const request = <D = any, R = any>(
  url: string,
  config: AxiosRequestConfig,
) => {
  return instance.request<D, ResponseType<R>>({
    method: 'get',
    ...config,
    url,
  });
};

service/api/index.ts

import { request } from '@/app/request';


export async function getDemo<D = PaginatorType<Services.DemoType>>(params?: Services.DemoParamType):Promise<ResponseType<D>>{
	return request<ResponseType<D>>('demo/index', {
		params
	});
}

页面中使用

import { useRequest } from 'ahooks';

const {data,loading} = useRequest(()=>getDemo())

代码中的几个方法根据自己需要写一下就行

一定要使用ahooks里的useRequest

liuqiandev avatar Dec 23 '23 04:12 liuqiandev

我现在用 ahooks@3 + axios 单独做请求了,暂时放弃 max 里面的 request 了

请问能分享下完整的代码么?

app/request/index.ts

export const instance = axios.create({
  timeout: 10000,
  baseURL: baseHost(),
});


instance.interceptors.request.use(
  (config) => {
    Object.assign(config, { headers: getHeaders() });
    if (config.method === 'post') {
      Object.assign(config, { data: dataAssign(config.data, true) });
    }
    if (config.method === 'get') {
      Object.assign(config, { params: dataAssign(config.params, true) });
    }
    return { ...config };
  },
  (error) => {
    if (error.request) {
      showNotice(7, `请求错误`, `未接收到系统返回,请重试`);
    } else {
      showNotice(7, `系统错误`, `系统请求错误,请重试`);
    }
  },
);


instance.interceptors.response.use(
  (response) => {
    const { data = {} as any } = response;

    const {
      errorMessage = '系统异常,请稍后再试',
      errorCode,
      showType = 0,
    } = data;
    if (data.success === false) {
      let tips = '登录状态验证错误,请重新登录';
      if (errorCode <= -99900) {
        logout();
      } else {
        tips = `[${errorCode}]${errorMessage ?? '未返回错误信息'}`;
        showNotice(showType, `系统错误`, tips);
      }
      throw new Error(tips);
    } else {
      showNotice(showType, `系统提示`, errorMessage);
      return data;
    }
  },
  (error) => {
    let msg = '系统请求错误,请重试';
    if (error.response) {
      const { status } = error.response;
      msg = `系统响应错误,错误码:[${status}]`;
      showNotice(7, `响应错误`, msg);
    } else {
      showNotice(7, `系统错误`, msg);
    }
    const serverError = new Error(msg);
    serverError.name = 'ServerError';
    return Promise.reject(serverError);
  },
);


export const request = <D = any, R = any>(
  url: string,
  config: AxiosRequestConfig,
) => {
  return instance.request<D, ResponseType<R>>({
    method: 'get',
    ...config,
    url,
  });
};

service/api/index.ts

import { request } from '@/app/request';


export async function getDemo<D = PaginatorType<Services.DemoType>>(params?: Services.DemoParamType):Promise<ResponseType<D>>{
	return request<ResponseType<D>>('demo/index', {
		params
	});
}

页面中使用

import { useRequest } from 'ahooks';

const {data,loading} = useRequest(()=>getDemo())

代码中的几个方法根据自己需要写一下就行

一定要使用ahooks里的useRequest

好的,谢谢啦

dialYun avatar Dec 23 '23 04:12 dialYun