antd pro 有默认的响应格式,如下:
export interface response {
  success: boolean; // if request is success
  data?: any; // response data
  errorCode?: string; // code for errorType
  errorMessage?: string; // message display to user
  showType?: number; // error display type: 0 silent; 1 message.warn; 2 message.error; 4 notification; 9 page
  traceId?: string; // Convenient for back-end Troubleshooting: unique request ID
  host?: string; // onvenient for backend Troubleshooting: host of current access server
}

但是呢,几乎没有服务端会是这样的格式,可能更多的是如下格式:

{"code":1,"message":"","data":null,"status":400}

code=业务码,message=提示信息,data=数据,status=200状态码

很多服务端api不区分状态码直接200,然后根据code做正确判断;

不管是否状态码响应,都需要将响应转换为支持的格式,需要修改处理:

//app.ts配置
export const request: RequestConfig = {
  //错误出理器
  errorHandler: errorHandler,
  //请求拦截器,根据需要决定是否需要
  requestInterceptors: [authHeaderInterceptor],
  errorConfig: {
    //响应体格式转换器
    adaptor: errorConfigAdaptor,
  }
};

//错误出理器:这段代码是plug-request 里面默认的处理,只是修改了一部分@custom
export const errorHandler = (error: RequestError) => {
  //@custom
  //这个是下面配置的响应体转换器
  const errorAdaptor =
    error?.request?.options?.errorConfig?.adaptor || ((resData: any) => resData);
  const DEFAULT_ERROR_PAGE = '/exception';

  // @ts-ignore
  if (error?.request?.options?.skipErrorHandler) {
    throw error;
  }
  let errorInfo: ErrorInfoStructure | undefined;

  if (error.name === 'ResponseError' && error.data && error.request) {
    const ctx: Context = {
      req: error.request,
      res: error.response,
    };
    errorInfo = errorAdaptor(error.data, ctx);
    //@custom 
    //
    //非标准格式或异常状态码时处理,符合标准格式转为BizError
    if (errorInfo?.success === undefined) {
      errorInfo = {
        success: false,
        errorMessage: `${ctx?.res?.statusText} (#${ctx?.res?.status})`,
      };
    }
    error.message = errorInfo?.errorMessage || error.message;
    error.data = error.data;
    error.info = errorInfo;
  }
  errorInfo = error.info;

  if (errorInfo) {
    const errorMessage = errorInfo?.errorMessage;
    const errorCode = errorInfo?.errorCode;
    const errorPage =
      error?.request?.options?.errorConfig?.errorPage || DEFAULT_ERROR_PAGE;

    switch (errorInfo?.showType) {
      case ErrorShowType.SILENT:
        // do nothing
        break;
      case ErrorShowType.WARN_MESSAGE:
        message.warn(errorMessage);
        break;
      case ErrorShowType.ERROR_MESSAGE:
        message.error(errorMessage);
        break;
      case ErrorShowType.NOTIFICATION:
        notification.open({
          description: errorMessage,
          message: errorCode,
        });
        break;
      case ErrorShowType.REDIRECT:
        // @ts-ignore
        history.push({
          pathname: errorPage,
          query: {errorCode, errorMessage},
        });
        // redirect to error page
        break;
      default:
        message.error(errorMessage);
        break;
    }
  } else {
    message.error(error.message || 'Request error, please retry.');
  }
  throw error;
}

//响应体格式转换器 这里处理后,就符合规格定时了,但是非标转异常的状态码不会处理
export const errorConfigAdaptor = (resData: any | { code: number, message: string, name?: string, data: any, status: number, [key: string]: any }, ctx) => {
  if (resData?.code && resData?.status) {
    return {
      success: resData.status >= 200 && resData.status < 300,
      //yii框架抛出异常时有name,具体可以根据服务端响应处理
      errorMessage: resData?.message != '' && resData.message || resData?.name != '' && resData.name || '',
      errorCode: resData?.code || '',
      data: resData?.data || resData,
      ...resData
    };
  }
  return resData;
};

这样的处理,request时也会抛出异常,但是有message提示;
request().then(res).catch(res);

之前一直想在出理器中不抛出异常,但是当出现400等状态码时,就会进入.then(res) 这样可能会造成误判,所以还是抛出异常吧,手动catch(res)一下也不碍事;


曾经的少年
9 声望0 粉丝

擅长PHP,mysql,熟悉HTML、CSS、JavaScript能做网站,了解react、typescript能上手,