2
0
mirror of https://github.com/tenrok/axios.git synced 2026-05-15 11:59:42 +03:00

fix: added a option to choose between legacy and the new request/response interceptor ordering

* test: add request interceptor tests for legacy and ordered execution

* feat: add legacy interceptor request/response ordering option

---------

Co-authored-by: Jay <jasonsaayman@gmail.com>
This commit is contained in:
Willian Agostini
2026-01-30 03:12:04 -03:00
committed by GitHub
parent 44b7c9f0c4
commit 569f028a58
6 changed files with 89 additions and 17 deletions
+3
View File
@@ -615,6 +615,9 @@ These are the available config options for making requests. Only the `url` is re
// throw ETIMEDOUT error instead of generic ECONNABORTED on request timeouts
clarifyTimeoutError: false,
// use the legacy interceptor request/response ordering
legacyInterceptorReqResOrdering: true, // default
},
env: {
+1
View File
@@ -302,6 +302,7 @@ declare namespace axios {
silentJSONParsing?: boolean;
forcedJSONParsing?: boolean;
clarifyTimeoutError?: boolean;
legacyInterceptorReqResOrdering?: boolean;
}
interface GenericAbortSignal {
Vendored
+1
View File
@@ -332,6 +332,7 @@ export interface TransitionalOptions {
silentJSONParsing?: boolean;
forcedJSONParsing?: boolean;
clarifyTimeoutError?: boolean;
legacyInterceptorReqResOrdering?: boolean;
}
export interface GenericAbortSignal {
+11 -2
View File
@@ -8,6 +8,7 @@ import mergeConfig from './mergeConfig.js';
import buildFullPath from './buildFullPath.js';
import validator from '../helpers/validator.js';
import AxiosHeaders from './AxiosHeaders.js';
import transitionalDefaults from '../defaults/transitional.js';
const validators = validator.validators;
@@ -80,7 +81,8 @@ class Axios {
validator.assertOptions(transitional, {
silentJSONParsing: validators.transitional(validators.boolean),
forcedJSONParsing: validators.transitional(validators.boolean),
clarifyTimeoutError: validators.transitional(validators.boolean)
clarifyTimeoutError: validators.transitional(validators.boolean),
legacyInterceptorReqResOrdering: validators.transitional(validators.boolean)
}, false);
}
@@ -139,7 +141,14 @@ class Axios {
synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;
requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);
const transitional = config.transitional || transitionalDefaults;
const legacyInterceptorReqResOrdering = transitional && transitional.legacyInterceptorReqResOrdering;
if (legacyInterceptorReqResOrdering) {
requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);
} else {
requestInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);
}
});
const responseInterceptorChain = [];
+2 -1
View File
@@ -3,5 +3,6 @@
export default {
silentJSONParsing: true,
forcedJSONParsing: true,
clarifyTimeoutError: false
clarifyTimeoutError: false,
legacyInterceptorReqResOrdering: true
};
+71 -14
View File
@@ -91,6 +91,63 @@ describe('interceptors', function () {
});
});
it('should execute request interceptor in legacy order', function (done) {
let sequence = '';
axios.interceptors.request.use(function (config) {
sequence += '1';
return config;
});
axios.interceptors.request.use(function (config) {
sequence += '2';
return config;
});
axios.interceptors.request.use(function (config) {
sequence += '3';
return config;
});
axios({
url: '/foo',
});
getAjaxRequest().then(function (request) {
expect(sequence).toBe('321');
done();
});
});
it('should execute request interceptor in order', function (done) {
let sequence = '';
axios.interceptors.request.use(function (config) {
sequence += '1';
return config;
});
axios.interceptors.request.use(function (config) {
sequence += '2';
return config;
});
axios.interceptors.request.use(function (config) {
sequence += '3';
return config;
});
axios({
url: '/foo',
transitional: {
legacyInterceptorReqResOrdering: false
}
});
getAjaxRequest().then(function (request) {
expect(sequence).toBe('123');
done();
});
});
it('runs the interceptor if runWhen function is provided and resolves to true', function (done) {
function onGetCall(config) {
return config.method === 'get';
@@ -343,7 +400,7 @@ describe('interceptors', function () {
function fireRequestAndExpect(expectation) {
let response;
axios('/foo').then(function(data) {
axios('/foo').then(function (data) {
response = data;
});
getAjaxRequest().then(function (request) {
@@ -352,7 +409,7 @@ describe('interceptors', function () {
responseText: 'OK'
});
setTimeout(function() {
setTimeout(function () {
expectation(response)
}, 100);
});
@@ -384,10 +441,10 @@ describe('interceptors', function () {
});
it('then only the last interceptor\'s result is returned', function (done) {
axios.interceptors.response.use(function() {
axios.interceptors.response.use(function () {
return 'response 1';
});
axios.interceptors.response.use(function() {
axios.interceptors.response.use(function () {
return 'response 2';
});
@@ -398,10 +455,10 @@ describe('interceptors', function () {
});
it('then every interceptor receives the result of it\'s predecessor', function (done) {
axios.interceptors.response.use(function() {
axios.interceptors.response.use(function () {
return 'response 1';
});
axios.interceptors.response.use(function(response) {
axios.interceptors.response.use(function (response) {
return [response, 'response 2'];
});
@@ -414,7 +471,7 @@ describe('interceptors', function () {
describe('and when the fulfillment-interceptor throws', function () {
function fireRequestCatchAndExpect(expectation) {
axios('/foo').catch(function(data) {
axios('/foo').catch(function (data) {
// dont handle result
});
getAjaxRequest().then(function (request) {
@@ -423,14 +480,14 @@ describe('interceptors', function () {
responseText: 'OK'
});
setTimeout(function() {
setTimeout(function () {
expectation()
}, 100);
});
}
it('then the following fulfillment-interceptor is not called', function (done) {
axios.interceptors.response.use(function() {
axios.interceptors.response.use(function () {
throw Error('throwing interceptor');
});
const interceptor2 = jasmine.createSpy('interceptor2');
@@ -443,10 +500,10 @@ describe('interceptors', function () {
});
it('then the following rejection-interceptor is called', function (done) {
axios.interceptors.response.use(function() {
axios.interceptors.response.use(function () {
throw Error('throwing interceptor');
});
const unusedFulfillInterceptor = function() {};
const unusedFulfillInterceptor = function () { };
const rejectIntercept = jasmine.createSpy('rejectIntercept');
axios.interceptors.response.use(unusedFulfillInterceptor, rejectIntercept);
@@ -457,12 +514,12 @@ describe('interceptors', function () {
});
it('once caught, another following fulfill-interceptor is called again (just like in a promise chain)', function (done) {
axios.interceptors.response.use(function() {
axios.interceptors.response.use(function () {
throw Error('throwing interceptor');
});
const unusedFulfillInterceptor = function() {};
const catchingThrowingInterceptor = function() {};
const unusedFulfillInterceptor = function () { };
const catchingThrowingInterceptor = function () { };
axios.interceptors.response.use(unusedFulfillInterceptor, catchingThrowingInterceptor);
const interceptor3 = jasmine.createSpy('interceptor3');