3-2、错误信息增强

2019-12-05  本文已影响0人  Eileen_1d88

上一节我们捕获了几类ajax错误信息,但是对于错误信息提供得不够详细,我们希望对外提供得错误信息不仅仅包含错误文本信息,还包括请求对象配置config,错误代码code,XMLHttpRequest对象实例request以及自定义响应对象的response

axios({
  method: 'get',
  url: '/error/timeout',
  timeout: 2000
}).then((res) => {
  console.log(res)
}).catch((e: AxiosError) => {
  console.log(e.message)
  console.log(e.request)
  console.log(e.code)
})

这样对于应用方来说,他们就可以捕获到这些错误的详细信息,做进一步的处理。
那么接下来我们就来对错误信息做增强。

interface AxiosError extends Error {
  config: AxiosRequestConfig,
  code?: string | null,
  request?: XMLHttpRequest,
  reponse: AxiosResponse,
  isAxiosError: boolean
}

2、实现AxiosError类
src/helpers/error.ts

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

export class AxiosError extends Error {
  isAxiosError: boolean
  config: AxiosRequestConfig
  code?: string | null
  request?: XMLHttpRequest
  reponse?: AxiosResponse

  constructor(
    message: string,
    config: AxiosRequestConfig,
    code?: string | null,
    request?: XMLHttpRequest,
    reponse?: AxiosResponse
  ) {
    super(message) // 调用父类Error的constructor(message)
    this.config = config
    this.code = code
    this.request = request
    this.reponse = reponse
    this.isAxiosError = true
    // 为了解决ts继承一些内置对象时候的坑
    Object.setPrototypeOf(this, AxiosError.prototype)
  }
}

export function createError(
  message: string,
  config: AxiosRequestConfig,
  code?: string | null,
  request?: XMLHttpRequest,
  response?: AxiosResponse
): AxiosError {
  const error = new AxiosError(message, config, code, request, response)
  return error
}

另外,为了方便使用,我们暴露一个createError方法。
修改xhr.ts中相关内容

import { AxiosRequestConfig, AxiosPromise, AxiosResponse } from "./types";
import { parseHeaders } from "./helpers/headers";
import { transformResponse } from "./helpers/data";
import { createError } from "./helpers/error";

export default function xhr(config: AxiosRequestConfig): AxiosPromise {
  return new Promise((resolve, reject) => {
    // method和data可能没有, 所以给出默认值
    const {
      url,
      method = 'get',
      data = null,
      headers,
      responseType,
      timeout
    } = config
    const request = new XMLHttpRequest()
    if (responseType) {
      request.responseType = responseType
    }
    if (timeout) {
      request.timeout = timeout
    }
    request.open(method.toUpperCase(), url)
    Object.keys(headers).forEach((name) => {
      request.setRequestHeader(name, headers[name])
    })
    request.onerror = function handleError() {
      reject(createError('Network Error', config, null, request))
    }
    request.onreadystatechange = function handleLoad() {
      // request.readyState不是4,说明请求还未返回
      if (request.readyState !== 4) {
        return
      }
      // 在请求未返回的时候,status为0,
      // 当XMLHttpRequest出错的时候,status也为0
      // 所以status为0的时候,不做处理
      if (request.status === 0) {
        return
      }
      const responseHeaders = request.getAllResponseHeaders()
      const responseData = responseType && responseType !== 'text' ? request.response : request.responseText
      const response: AxiosResponse = {
        data: transformResponse(responseData),
        headers: parseHeaders(responseHeaders),
        status: request.status,
        statusText: request.statusText,
        config,
        request
      }
      handleResponse(response)
    }
    request.ontimeout = function handleTimeout() {
      reject(createError(`Timeout of ${timeout}ms exceeded`, config, 'ECONNABORTED', request))
    }
    request.send(data)

    function handleResponse(response: AxiosResponse) {
      if (response.status >= 200 && response.status < 300) {
        resolve(response)
      } else {
        reject(createError(`Request failed width status code ${response.status}`, config, null, request, response))
      }
    }
  })
}
import axios from './core/axios'
export * from './types'
export default axios

那么在测试demo中我们就可以这样

import axios, { AxiosError }from '../../src/index'

axios({
  method: 'get',
  url: '/api/error/get1'
}).then((res) => {
  console.log(res)
}).catch((e: AxiosError) => {
console.log(e)
})

axios({
  method: 'get',
  url: '/api/error/get'
}).then((res) => {
  console.log(res)
}).catch((e: AxiosError) => {
  console.log(e)
})

setTimeout(() => {
  axios({
    method: 'get',
    url: '/api/error/get'
  }).then((res) => {
    console.log(res)
  }).catch((e: AxiosError) => {
    console.log(e)
  })
}, 5000)

axios({
  method: 'get',
  url: '/api/error/timeout',
  timeout: 2000
}).then((res) => {
  console.log(res)
}).catch((e: AxiosError) => {
  console.log(e)
})

const NODE_ENV = process.env.NODE_ENV || 'development'
if(NODE_ENV === 'development' && module.hot){
  module.hot.accept();
}

如此,我们对错误逻辑的处理就告一段落。接下来,我们需要扩展ts-axios,提供更多API。

上一篇下一篇

猜你喜欢

热点阅读