美文网首页
3-2、错误信息增强

3-2、错误信息增强

作者: Eileen_1d88 | 来源:发表于2019-12-05 17:41 被阅读0次

    上一节我们捕获了几类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)
    })
    

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

    • 创建AxiosError类
      1、创建AxiosError接口类型
    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))
          }
        }
      })
    }
    
    • 导出类型定义
      把之前src/index.ts中的内容move到src/core/axios.ts中,index.ts中的内容改为
    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。

    相关文章

      网友评论

          本文标题:3-2、错误信息增强

          本文链接:https://www.haomeiwen.com/subject/ibndgctx.html