# 1. 前言

在上篇文章中,我们处理异常时仅仅获取了异常的文本信息,但是对出现异常的请求的详细信息并未获取,我们期望在请求发生异常时我们能获取到该请求的对象配置 config,错误代码 codeXMLHttpRequest 对象实例 request以及响应对象 response,方便用户进行异常定位排查,如下:

axios({
  method: "get",
  url: "/api/handleError1",
})
  .then((res) => {
    console.log(res);
  })
  .catch((e) => {
    console.log(e.message);
    console.log(e.config);
    console.log(e.request);
    console.log(e.code);
  });
1
2
3
4
5
6
7
8
9
10
11
12
13

那么,接下来,我们就来增强异常信息。

# 2. 异常信息接口类型定义

根据我们所要获取的几个异常信息,我们先在src/types.index.ts中定义一下异常信息的接口类型,如下:

export interface AxiosError extends Error {
  config: AxiosRequestConfig;
  code?: string | null | number;
  request?: any;
  response?: AxiosResponse;
}
1
2
3
4
5
6

# 3. 创建 AxiosError 类

定义好接口类型以后,我们就来创建一个AxiosError类,该类继承自内置的Error类,我们在src/helpers路径下创建error.ts文件,如下:

// src/helpers/error.ts

import { AxiosRequestConfig, AxiosResponse } from "../types";

export class AxiosError extends Error {
  private config: AxiosRequestConfig;
  private request?: any;
  private code?: string | null | number;
  private response?: AxiosResponse;

  constructor(
    message: string,
    config: AxiosRequestConfig,
    request?: any,
    code?: string | null | number,
    response?: AxiosResponse
  ) {
    super(message);

    this.config = config;
    this.request = request;
    this.code = code;
    this.response = response;

    Object.setPrototypeOf(this, AxiosError.prototype);
  }
}

export function createError(
  message: string,
  config: AxiosRequestConfig,
  code: string | null | number,
  request?: any,
  response?: AxiosResponse
) {
  const error = new AxiosError(message, config, code, request, response);
  return error;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

AxiosError 类继承于 Error 类,添加了一些自己的属性:configcoderequestresponseisAxiosError 等属性。除此之外,我们还创建了一个用于快速创建AxiosError 类实例的工厂方法createError,后续我们可以直接调用该方法,并传入相关的参数来快速创建AxiosError 类实例。

OK,定义好之后我们就可以使用一下。

# 4. 使用 AxiosError 类

AxiosError 类使用起来非常简单,我们只需把上篇文章中在src/xhr.ts中抛出异常的地方的new Error()改成createError就好啦。

// src/xhr.ts

import { AxiosError } from "./helpers/error";

request.onerror = function() {
  reject(createError("Net Error", config, null, request));
};

request.ontimeout = function() {
  reject(
    createError(`Timeout of ${timeout} ms exceeded`, config, "TIMEOUT", request)
  );
};

function handleResponse(response: AxiosResponse): void {
  if (response.status >= 200 && response.status < 300) {
    resolve(response);
  } else {
    reject(
      createError(
        `Request failed with status code ${response.status}`,
        config,
        null,
        request.status,
        response
      )
    );
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

改写完成后,我们就可以编写demo来测试一下,看看效果如何。

# 5. 编写 demo

上篇文章中的demo我们完全可以复用,只需在异常捕获那里稍加改动,加上我们开头想要获取的几个异常信息打印即可,看看是否能够获取到。

// examples/handleError/app.ts

axios({
  method: "get",
  url: "/api/handleError1",
})
  .then((res) => {
    console.log(res);
  })
  .catch((e) => {
    console.log(e.message);
    console.log(e.config);
    console.log(e.request);
    console.log(e.code);
  });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

OK,接下来,我们就可以将项目运行起来,打开 chrome 浏览器,访问 http://localhost:8000/ (opens new window) 即可访问我们的 demo 了,我们点击 handleError,通过F12的控制台我们可以看到:我们想要的异常信息已经可以获取到了。

OK,异常处理这块我们就已经搞定了!