错误处理1
我们在 core
文件下创建 AxiosError.js
文件,在文件里实现 AxiosError
错误类。AxiosError 类做的事情非常简单,就是对浏览器原生的 Error
类进行继承、扩展。我们直接看代码注释
"use strict";
var utils = require("../utils");
/**
* 通过指定的消息、错误码等参数创建一个错误实例
* @param {string} message 错误消息.
* @param {string} [code] 错误码 (例如: 'ECONNABORTED').
* @param {Object} [config] axios的配置对象.
* @param {Object} [request] XMLHttpRequest实例.
* @param {Object} [response] 请求的响应对象.
* @returns {Error} The created error.
*/
function AxiosError(message, code, config, request, response) {
Error.call(this); // 继承Error的属性
if (Error.captureStackTrace) {
Error.captureStackTrace(this); // 错误信息的堆栈追踪
}
this.message = message;
this.name = "AxiosError";
code && (this.code = code);
config && (this.config = config);
request && (this.request = request);
response && (this.response = response);
}
// AxiosError继承Error的原型(Error.prototype), 同时继承toJSON方法
utils.inherits(AxiosError, Error, {
toJSON: function toJSON() {
return {
// 标准浏览器的错误信息
message: this.message,
name: this.name,
// Microsoft的错误信息
description: this.description,
number: this.number,
// Mozilla的错误信息
fileName: this.fileName,
lineNumber: this.lineNumber,
columnNumber: this.columnNumber,
stack: this.stack,
// Axios本身的一些信息
config: this.config,
code: this.code,
status:
this.response && this.response.status ? this.response.status : null,
};
},
});
var prototype = AxiosError.prototype;
var descriptors = {};
// 错误码
[
"ERR_BAD_OPTION_VALUE",
"ERR_BAD_OPTION",
"ECONNABORTED",
"ETIMEDOUT",
"ERR_NETWORK",
"ERR_FR_TOO_MANY_REDIRECTS",
"ERR_DEPRECATED",
"ERR_BAD_RESPONSE",
"ERR_BAD_REQUEST",
"ERR_CANCELED",
// eslint-disable-next-line func-names
].forEach(function (code) {
descriptors[code] = { value: code };
});
// 把错误码作为AxiosError的静态属性
// 这样就可以通过AxiosError.ERR_BAD_REQUEST的方式访问错误码
Object.defineProperties(AxiosError, descriptors);
// 表明一个对象是AxiosError实例的标志
Object.defineProperty(prototype, "isAxiosError", { value: true });
// 通过一个错误实例(error)来创建一个axios错误(axiosError), 而不用通过new AxiosError()的方式
AxiosError.from = function (
error,
code,
config,
request,
response,
customProps
) {
var axiosError = Object.create(prototype);
// 把error的属性拷贝到axiosError中
utils.toFlatObject(error, axiosError, function filter(obj) {
// 自定义的过滤函数,用于决定是否拷贝obj,返回false则不拷贝
// obj是Error.prototype时,不拷贝obj
return obj !== Error.prototype;
});
// axiosError作为AxiosError的this上下文,等同于new AxiosError()
AxiosError.call(axiosError, error.message, code, config, request, response);
axiosError.name = error.name;
customProps && Object.assign(axiosError, customProps);
return axiosError;
};
module.exports = AxiosError;
我们在 AxiosError
中用了 utils.inherits
跟 utils.toFlatObject
方法,现在我们来实现它们
/**
* constructor继承superConstructor的原型方法
* @param {function} constructor 子类
* @param {function} superConstructor 父类
* @param {object} [props] 用于扩展子类的原型方法
* @param {object} [descriptors] 属性描述符,可以往constructor.prototype上添加属性
*/
function inherits(constructor, superConstructor, props, descriptors) {
constructor.prototype = Object.create(
superConstructor.prototype,
descriptors
);
constructor.prototype.constructor = constructor;
props && Object.assign(constructor.prototype, props);
}
/**
* 把sourceObj上的内容,包括原型链(Object.prototype除外)上的属性、方法拷贝到destObj上
* @param {Object} sourceObj 源对象
* @param {Object} [destObj] 目的对象
* @param {Function} [filter] 自定义的过滤函数,用于决定是否拷贝obj,返回false则不拷贝
* @returns {Object}
*/
function toFlatObject(sourceObj, destObj, filter) {
var props;
var i;
var prop;
var merged = {};
destObj = destObj || {};
do {
props = Object.getOwnPropertyNames(sourceObj);
i = props.length;
while (i-- > 0) {
prop = props[i];
if (!merged[prop]) {
destObj[prop] = sourceObj[prop];
merged[prop] = true;
}
}
sourceObj = Object.getPrototypeOf(sourceObj);
} while (
sourceObj &&
(!filter || filter(sourceObj, destObj)) &&
sourceObj !== Object.prototype
);
return destObj;
}