mirror of
https://github.com/tenrok/axios.git
synced 2026-06-17 19:21:29 +03:00
* fix: turn AxiosError into a native error (#5394) Being an object returned by the 'Error' constructor turns something into a 'native error'. * fix: simplify code in AxiosError * fix: simplify code in AxiosError * refactor: implement AxiosError as a class * refactor: implement CanceledError as a class This turns CanceledError into a native error. * refactor: simplify AxiosError.toJSON * fix: improve error code handling in `AxiosError.from` If no error code is provided, use the code from the underlying error. * fix: set error status in `AxiosError.constructor` If a response is passed to the constructor, set the response status as a property. * fix: remove unnecessary async --------- Co-authored-by: Jay <jasonsaayman@gmail.com>
This commit is contained in:
+15
-18
@@ -1,25 +1,22 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import AxiosError from '../core/AxiosError.js';
|
import AxiosError from '../core/AxiosError.js';
|
||||||
import utils from '../utils.js';
|
|
||||||
|
|
||||||
/**
|
class CanceledError extends AxiosError {
|
||||||
* A `CanceledError` is an object that is thrown when an operation is canceled.
|
/**
|
||||||
*
|
* A `CanceledError` is an object that is thrown when an operation is canceled.
|
||||||
* @param {string=} message The message.
|
*
|
||||||
* @param {Object=} config The config.
|
* @param {string=} message The message.
|
||||||
* @param {Object=} request The request.
|
* @param {Object=} config The config.
|
||||||
*
|
* @param {Object=} request The request.
|
||||||
* @returns {CanceledError} The created error.
|
*
|
||||||
*/
|
* @returns {CanceledError} The created error.
|
||||||
function CanceledError(message, config, request) {
|
*/
|
||||||
// eslint-disable-next-line no-eq-null,eqeqeq
|
constructor(message, config, request) {
|
||||||
AxiosError.call(this, message == null ? 'canceled' : message, AxiosError.ERR_CANCELED, config, request);
|
super(message == null ? 'canceled' : message, AxiosError.ERR_CANCELED, config, request);
|
||||||
this.name = 'CanceledError';
|
this.name = 'CanceledError';
|
||||||
|
this.__CANCEL__ = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
utils.inherits(CanceledError, AxiosError, {
|
|
||||||
__CANCEL__: true
|
|
||||||
});
|
|
||||||
|
|
||||||
export default CanceledError;
|
export default CanceledError;
|
||||||
|
|||||||
+63
-100
@@ -2,109 +2,72 @@
|
|||||||
|
|
||||||
import utils from '../utils.js';
|
import utils from '../utils.js';
|
||||||
|
|
||||||
/**
|
class AxiosError extends Error {
|
||||||
* Create an Error with the specified message, config, error code, request and response.
|
static from(error, code, config, request, response, customProps) {
|
||||||
*
|
const axiosError = new AxiosError(error.message, code || error.code, config, request, response);
|
||||||
* @param {string} message The error message.
|
axiosError.cause = error;
|
||||||
* @param {string} [code] The error code (for example, 'ECONNABORTED').
|
axiosError.name = error.name;
|
||||||
* @param {Object} [config] The config.
|
customProps && Object.assign(axiosError, customProps);
|
||||||
* @param {Object} [request] The request.
|
return axiosError;
|
||||||
* @param {Object} [response] The response.
|
}
|
||||||
*
|
|
||||||
* @returns {Error} The created error.
|
|
||||||
*/
|
|
||||||
function AxiosError(message, code, config, request, response) {
|
|
||||||
Error.call(this);
|
|
||||||
|
|
||||||
if (Error.captureStackTrace) {
|
/**
|
||||||
Error.captureStackTrace(this, this.constructor);
|
* Create an Error with the specified message, config, error code, request and response.
|
||||||
} else {
|
*
|
||||||
this.stack = (new Error()).stack;
|
* @param {string} message The error message.
|
||||||
}
|
* @param {string} [code] The error code (for example, 'ECONNABORTED').
|
||||||
|
* @param {Object} [config] The config.
|
||||||
|
* @param {Object} [request] The request.
|
||||||
|
* @param {Object} [response] The response.
|
||||||
|
*
|
||||||
|
* @returns {Error} The created error.
|
||||||
|
*/
|
||||||
|
constructor(message, code, config, request, response) {
|
||||||
|
super(message);
|
||||||
|
this.name = 'AxiosError';
|
||||||
|
this.isAxiosError = true;
|
||||||
|
code && (this.code = code);
|
||||||
|
config && (this.config = config);
|
||||||
|
request && (this.request = request);
|
||||||
|
if (response) {
|
||||||
|
this.response = response;
|
||||||
|
this.status = response.status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.message = message;
|
toJSON() {
|
||||||
this.name = 'AxiosError';
|
return {
|
||||||
code && (this.code = code);
|
// Standard
|
||||||
config && (this.config = config);
|
message: this.message,
|
||||||
request && (this.request = request);
|
name: this.name,
|
||||||
if (response) {
|
// Microsoft
|
||||||
this.response = response;
|
description: this.description,
|
||||||
this.status = response.status ? response.status : null;
|
number: this.number,
|
||||||
}
|
// Mozilla
|
||||||
|
fileName: this.fileName,
|
||||||
|
lineNumber: this.lineNumber,
|
||||||
|
columnNumber: this.columnNumber,
|
||||||
|
stack: this.stack,
|
||||||
|
// Axios
|
||||||
|
config: utils.toJSONObject(this.config),
|
||||||
|
code: this.code,
|
||||||
|
status: this.status,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
utils.inherits(AxiosError, Error, {
|
// This can be changed to static properties as soon as the parser options in .eslint.cjs are updated.
|
||||||
toJSON: function toJSON() {
|
AxiosError.ERR_BAD_OPTION_VALUE = 'ERR_BAD_OPTION_VALUE';
|
||||||
return {
|
AxiosError.ERR_BAD_OPTION = 'ERR_BAD_OPTION';
|
||||||
// Standard
|
AxiosError.ECONNABORTED = 'ECONNABORTED';
|
||||||
message: this.message,
|
AxiosError.ETIMEDOUT = 'ETIMEDOUT';
|
||||||
name: this.name,
|
AxiosError.ERR_NETWORK = 'ERR_NETWORK';
|
||||||
// Microsoft
|
AxiosError.ERR_FR_TOO_MANY_REDIRECTS = 'ERR_FR_TOO_MANY_REDIRECTS';
|
||||||
description: this.description,
|
AxiosError.ERR_DEPRECATED = 'ERR_DEPRECATED';
|
||||||
number: this.number,
|
AxiosError.ERR_BAD_RESPONSE = 'ERR_BAD_RESPONSE';
|
||||||
// Mozilla
|
AxiosError.ERR_BAD_REQUEST = 'ERR_BAD_REQUEST';
|
||||||
fileName: this.fileName,
|
AxiosError.ERR_CANCELED = 'ERR_CANCELED';
|
||||||
lineNumber: this.lineNumber,
|
AxiosError.ERR_NOT_SUPPORT = 'ERR_NOT_SUPPORT';
|
||||||
columnNumber: this.columnNumber,
|
AxiosError.ERR_INVALID_URL = 'ERR_INVALID_URL';
|
||||||
stack: this.stack,
|
|
||||||
// Axios
|
|
||||||
config: utils.toJSONObject(this.config),
|
|
||||||
code: this.code,
|
|
||||||
status: this.status
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const prototype = AxiosError.prototype;
|
|
||||||
const 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',
|
|
||||||
'ERR_NOT_SUPPORT',
|
|
||||||
'ERR_INVALID_URL'
|
|
||||||
// eslint-disable-next-line func-names
|
|
||||||
].forEach(code => {
|
|
||||||
descriptors[code] = {value: code};
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.defineProperties(AxiosError, descriptors);
|
|
||||||
Object.defineProperty(prototype, 'isAxiosError', {value: true});
|
|
||||||
|
|
||||||
// eslint-disable-next-line func-names
|
|
||||||
AxiosError.from = (error, code, config, request, response, customProps) => {
|
|
||||||
const axiosError = Object.create(prototype);
|
|
||||||
|
|
||||||
utils.toFlatObject(error, axiosError, function filter(obj) {
|
|
||||||
return obj !== Error.prototype;
|
|
||||||
}, prop => {
|
|
||||||
return prop !== 'isAxiosError';
|
|
||||||
});
|
|
||||||
|
|
||||||
const msg = error && error.message ? error.message : 'Error';
|
|
||||||
|
|
||||||
// Prefer explicit code; otherwise copy the low-level error's code (e.g. ECONNREFUSED)
|
|
||||||
const errCode = code == null && error ? error.code : code;
|
|
||||||
AxiosError.call(axiosError, msg, errCode, config, request, response);
|
|
||||||
|
|
||||||
// Chain the original error on the standard field; non-enumerable to avoid JSON noise
|
|
||||||
if (error && axiosError.cause == null) {
|
|
||||||
Object.defineProperty(axiosError, 'cause', { value: error, configurable: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
axiosError.name = (error && error.name) || 'Error';
|
|
||||||
|
|
||||||
customProps && Object.assign(axiosError, customProps);
|
|
||||||
|
|
||||||
return axiosError;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AxiosError;
|
export default AxiosError;
|
||||||
|
|||||||
@@ -12,4 +12,10 @@ describe('Cancel', function() {
|
|||||||
expect(cancel.toString()).toBe('CanceledError: Operation has been canceled.');
|
expect(cancel.toString()).toBe('CanceledError: Operation has been canceled.');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('should be a native error as checked by the NodeJS `isNativeError` function', function (){
|
||||||
|
if((typeof process !== 'undefined') && (process.release.name === 'node')){
|
||||||
|
let {isNativeError} = require('node:util/types');
|
||||||
|
expect(isNativeError(new CanceledError("My Canceled Error"))).toBeTruthy();
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import AxiosError from '../../../lib/core/AxiosError';
|
import AxiosError from '../../../lib/core/AxiosError';
|
||||||
|
|
||||||
|
|
||||||
describe('core::AxiosError', function() {
|
describe('core::AxiosError', function() {
|
||||||
it('should create an Error with message, config, code, request, response, stack and isAxiosError', function() {
|
it('should create an Error with message, config, code, request, response, stack and isAxiosError', function() {
|
||||||
const request = { path: '/foo' };
|
const request = { path: '/foo' };
|
||||||
@@ -49,6 +50,18 @@ describe('core::AxiosError', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should be a native error as checked by the NodeJS `isNativeError` function', function (){
|
||||||
|
if((typeof process !== 'undefined') && (process.release.name === 'node')){
|
||||||
|
let {isNativeError} = require('node:util/types');
|
||||||
|
expect(isNativeError(new AxiosError("My Axios Error"))).toBeTruthy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create an error using one of the static class properties as an error code', function (){
|
||||||
|
const myError = new AxiosError("My Axios Error", AxiosError.ECONNABORTED);
|
||||||
|
expect(myError.code).toEqual(AxiosError.ECONNABORTED);
|
||||||
|
});
|
||||||
|
|
||||||
it('should have status property when response was passed to the constructor', () => {
|
it('should have status property when response was passed to the constructor', () => {
|
||||||
const err = new AxiosError('test', 'foo', {}, {}, {status: 400});
|
const err = new AxiosError('test', 'foo', {}, {}, {status: 400});
|
||||||
expect(err.status).toBe(400);
|
expect(err.status).toBe(400);
|
||||||
|
|||||||
Reference in New Issue
Block a user