三种错误描述及基本解决方案
1.错误网络异常错误
当网络出现异常(比如网络不通)的时候,发送请求会触发XMLHTTPRequest对象实例的error事件。于是,我们可以在onerror的事件回调函数中捕获此类错误。
我们在xhr.ts中添加如下代码:
... request.onerror = function handleError() { reject(new Error('Network error')) } ...
2. 处理超时错误
我们可以设置某个请求的超时时间timeout,也就是当请求发送后超过某个时间仍然没有收到相应,则请求自动终止,并触发timeout事件。
请求默认的超时时间是0,即永不超时,所以我们首先需要允许程序可以配置超时时间:
export interface AxiosRequestConfig { // ... timeout?: number }
接着在xhr函数中添加如下代码:
const { /**...*/ timeout } = config if (timeout) { request.timeout = timeout } request.ontimeout = function handleTimeout() { reject(new Error('Timeout error')) }
3. 状态码错误
对于状态码不在200-300之间的,进行错误反馈
function handleResponse(response: AxiosResponse): void { // 错误情况3: 状态码错误 if (response.status >= 200 && response.status < 300) { resolve(response) } else { reject(new Error(`Request failed with the code ${response.status}`)) } }
错误信息增强
上述,我们能处理常见的异常错误情况,并接收到返回的错误信息。但是,我们可能还希望能接收到更多的错误信息,比如request的信息等等。
// 举个栗子,我们能在请求回调中,拿到更多错误信息,并进行分析 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) })
这样,我们就可以收集到更多的错误信息,并进一步做相应的处理,针对上述这个栗子,我们开始继续升级
1. 创建AxiosError类
我们首先定义AxiosError类型接口,用于外部使用
types/index.ts
export interface AxiosError extends Error { config: AxiosRequestConfig code?: string request?: any response?: AxiosResponse isAxiosError: boolean }
接着,我们创建error.ts文件,然后实现AxiosError类,它是集成于Error类。注意:接下来会有个坑,欲了解详情请点击查看我的另外一篇文章
/** helpers/error.ts */ import { AxiosRequestConfig, AxiosResponse } from '../types' export class AxiosError extends Error { isAxiosError: boolean config: AxiosRequestConfig code?: string | null request?: any response?: AxiosResponse constructor( message: string, config: AxiosRequestConfig, code?: string | null, request?: any, response?: AxiosResponse ) { super(message) this.config = config this.code = code this.request = request this.response = response this.isAxiosError = true /** 解决ts集成Error 等的一个坑 */ Object.setPrototypeOf(this, AxiosError.prototype) } } export function createError( message: string, config: AxiosRequestConfig, code?: string | null, request?: any, response?: AxiosResponse ) { const error = new AxiosError(message, config, code, request, response) return error }
最后,我们增强上面3个错误方法解决方案
... // 错误情况1: 网络错误 request.onerror = function handleError() { reject(createError('Network error', config, null, request)) } // 错误情况2: 超时错误 request.ontimeout = function handleTimeout() { reject(createError(`Timeout of ${timeout} error`, config, 'ECONNABORTED', request)) } // 错误情况3: 状态码错误 function handleResponse(response: AxiosResponse): void { if (response.status >= 200 && response.status < 300) { resolve(response) } else { reject( createError( `Request failed with the code ${response.status}`, config, null, request, response ) ) } ...