2
0
mirror of https://github.com/tenrok/axios.git synced 2026-06-20 20:00:40 +03:00

issue#2609 | Sasha | predictable axios requests (#2702)

* issue#2609 | Sasha | predictable axios requests

- axios requests are not delayed by pre-emptive promise creation by default
- add options to interceptors api ("synchronous" and "runWhen")
- add documentation and unit tests

* issue#2609 | Sasha | pull request feedback changes

* issue#2609 | Sasha | additional feedback changes

* issue#2609 | Sasha | put back try/catch

* issue#2609 | Sasha | add 2 adapter unit tests

- remove check for requestCancelled

Co-authored-by: ak71845 <alexandre.korotkov@kroger.com>
Co-authored-by: Xianming Zhong <chinesedfan@qq.com>
Co-authored-by: Jay <jasonsaayman@gmail.com>
This commit is contained in:
Sasha Korotkov
2021-03-01 04:11:35 -05:00
committed by GitHub
parent 535d0c45c1
commit 62d6256039
5 changed files with 339 additions and 24 deletions
+87 -8
View File
@@ -1,19 +1,98 @@
var axios = require('../../index');
describe('adapter', function () {
it('should support custom adapter', function (done) {
var called = false;
beforeEach(function () {
jasmine.Ajax.install();
});
afterEach(function () {
jasmine.Ajax.uninstall();
});
it('should support custom adapter', function (done) {
axios('/foo', {
adapter: function (config) {
called = true;
adapter: function barAdapter(config) {
return new Promise(function dispatchXhrRequest(resolve) {
var request = new XMLHttpRequest();
request.open('GET', '/bar');
request.onreadystatechange = function () {
resolve({
config: config,
request: request
});
};
request.send(null);
});
}
}).catch(console.log);
getAjaxRequest().then(function(request) {
expect(request.url).toBe('/bar');
done();
});
});
it('should execute adapter code synchronously', function (done) {
var asyncFlag = false;
axios('/foo', {
adapter: function barAdapter(config) {
return new Promise(function dispatchXhrRequest(resolve) {
var request = new XMLHttpRequest();
request.open('GET', '/bar');
request.onreadystatechange = function () {
resolve({
config: config,
request: request
});
};
expect(asyncFlag).toBe(false);
request.send(null);
});
}
}).catch(console.log);
asyncFlag = true;
getAjaxRequest().then(function() {
done();
});
});
it('should execute adapter code asynchronously when interceptor is present', function (done) {
var asyncFlag = false;
axios.interceptors.request.use(function (config) {
config.headers.async = 'async it!';
return config;
});
setTimeout(function () {
expect(called).toBe(true);
axios('/foo', {
adapter: function barAdapter(config) {
return new Promise(function dispatchXhrRequest(resolve) {
var request = new XMLHttpRequest();
request.open('GET', '/bar');
request.onreadystatechange = function () {
resolve({
config: config,
request: request
});
};
expect(asyncFlag).toBe(true);
request.send(null);
});
}
}).catch(console.log);
asyncFlag = true;
getAjaxRequest().then(function() {
done();
}, 100);
});
});
});
+171 -6
View File
@@ -9,25 +9,164 @@ describe('interceptors', function () {
axios.interceptors.response.handlers = [];
});
it('should add a request interceptor', function (done) {
it('should add a request interceptor (asynchronous by default)', function (done) {
var asyncFlag = false;
axios.interceptors.request.use(function (config) {
config.headers.test = 'added by interceptor';
expect(asyncFlag).toBe(true);
return config;
});
axios('/foo');
asyncFlag = true;
getAjaxRequest().then(function (request) {
request.respondWith({
status: 200,
responseText: 'OK'
});
expect(request.requestHeaders.test).toBe('added by interceptor');
done();
});
});
it('should add a request interceptor (explicitly flagged as asynchronous)', function (done) {
var asyncFlag = false;
axios.interceptors.request.use(function (config) {
config.headers.test = 'added by interceptor';
expect(asyncFlag).toBe(true);
return config;
}, null, { synchronous: false });
axios('/foo');
asyncFlag = true;
getAjaxRequest().then(function (request) {
expect(request.requestHeaders.test).toBe('added by interceptor');
done();
});
});
it('should add a request interceptor that is executed synchronously when flag is provided', function (done) {
var asyncFlag = false;
axios.interceptors.request.use(function (config) {
config.headers.test = 'added by synchronous interceptor';
expect(asyncFlag).toBe(false);
return config;
}, null, { synchronous: true });
axios('/foo');
asyncFlag = true;
getAjaxRequest().then(function (request) {
expect(request.requestHeaders.test).toBe('added by synchronous interceptor');
done();
});
});
it('should execute asynchronously when not all interceptors are explicitly flagged as synchronous', function (done) {
var asyncFlag = false;
axios.interceptors.request.use(function (config) {
config.headers.foo = 'uh oh, async';
expect(asyncFlag).toBe(true);
return config;
});
axios.interceptors.request.use(function (config) {
config.headers.test = 'added by synchronous interceptor';
expect(asyncFlag).toBe(true);
return config;
}, null, { synchronous: true });
axios.interceptors.request.use(function (config) {
config.headers.test = 'added by the async interceptor';
expect(asyncFlag).toBe(true);
return config;
});
axios('/foo');
asyncFlag = true;
getAjaxRequest().then(function (request) {
expect(request.requestHeaders.foo).toBe('uh oh, async');
/* request interceptors have a reversed execution order */
expect(request.requestHeaders.test).toBe('added by synchronous interceptor');
done();
});
});
it('runs the interceptor if runWhen function is provided and resolves to true', function (done) {
function onGetCall(config) {
return config.method === 'get';
}
axios.interceptors.request.use(function (config) {
config.headers.test = 'special get headers';
return config;
}, null, { runWhen: onGetCall });
axios('/foo');
getAjaxRequest().then(function (request) {
expect(request.requestHeaders.test).toBe('special get headers');
done();
});
});
it('does not run the interceptor if runWhen function is provided and resolves to false', function (done) {
function onPostCall(config) {
return config.method === 'post';
}
axios.interceptors.request.use(function (config) {
config.headers.test = 'special get headers';
return config;
}, null, { runWhen: onPostCall });
axios('/foo');
getAjaxRequest().then(function (request) {
expect(request.requestHeaders.test).toBeUndefined()
done();
});
});
it('does not run async interceptor if runWhen function is provided and resolves to false (and run synchronously)', function (done) {
var asyncFlag = false;
function onPostCall(config) {
return config.method === 'post';
}
axios.interceptors.request.use(function (config) {
config.headers.test = 'special get headers';
return config;
}, null, { synchronous: false, runWhen: onPostCall });
axios.interceptors.request.use(function (config) {
config.headers.sync = 'hello world';
expect(asyncFlag).toBe(false);
return config;
}, null, { synchronous: true });
axios('/foo');
asyncFlag = true
getAjaxRequest().then(function (request) {
expect(request.requestHeaders.test).toBeUndefined()
expect(request.requestHeaders.sync).toBe('hello world')
done();
});
});
it('should add a request interceptor with an onRejected block that is called if interceptor code fails', function (done) {
var rejectedSpy = jasmine.createSpy('rejectedSpy');
var error = new Error('deadly error');
axios.interceptors.request.use(function () {
throw error;
}, rejectedSpy, { synchronous: true });
axios('/foo');
getAjaxRequest().then(function () {
expect(rejectedSpy).toHaveBeenCalledWith(error);
done();
});
});
it('should add a request interceptor that returns a new config object', function (done) {
axios.interceptors.request.use(function () {
return {
@@ -237,6 +376,32 @@ describe('interceptors', function () {
});
});
it('should remove async interceptor before making request and execute synchronously', function (done) {
var asyncFlag = false;
var asyncIntercept = axios.interceptors.request.use(function (config) {
config.headers.async = 'async it!';
return config;
}, null, { synchronous: false });
var syncIntercept = axios.interceptors.request.use(function (config) {
config.headers.sync = 'hello world';
expect(asyncFlag).toBe(false);
return config;
}, null, { synchronous: true });
axios.interceptors.request.eject(asyncIntercept);
axios('/foo')
asyncFlag = true
getAjaxRequest().then(function (request) {
expect(request.requestHeaders.async).toBeUndefined();
expect(request.requestHeaders.sync).toBe('hello world');
done()
});
});
it('should execute interceptors before transformers', function (done) {
axios.interceptors.request.use(function (config) {
config.data.baz = 'qux';