Skip to content

Commit

Permalink
Revert "issue#2609 | Sasha | predictable axios requests (axios#2702)"
Browse files Browse the repository at this point in the history
This reverts commit 62d6256.
  • Loading branch information
xinjiexu committed Jul 2, 2021
1 parent e9965bf commit 8264cd0
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 337 deletions.
28 changes: 0 additions & 28 deletions README.md
Expand Up @@ -606,34 +606,6 @@ const instance = axios.create();
instance.interceptors.request.use(function () {/*...*/});
```

When you add request interceptors, they are presumed to be asynchronous by default. This can cause a delay
in the execution of your axios request when the main thread is blocked (a promise is created under the hood for
the interceptor and your request gets put on the bottom of the call stack). If your request interceptors are synchronous you can add a flag
to the options object that will tell axios to run the code synchronously and avoid any delays in request execution.

```js
axios.interceptors.request.use(function (config) {
config.headers.test = 'I am only a header!';
return config;
}, null, { synchronous: true });
```

If you want to execute a particular interceptor based on a runtime check,
you can add a `runWhen` function to the options object. The interceptor will not be executed **if and only if** the return
of `runWhen` is `false`. The function will be called with the config
object (don't forget that you can bind your own arguments to it as well.) This can be handy when you have an
asynchronous request interceptor that only needs to run at certain times.

```js
function onGetCall(config) {
return config.method === 'get';
}
axios.interceptors.request.use(function (config) {
config.headers.test = 'special get headers';
return config;
}, null, { runWhen: onGetCall });
```

## Handling Errors

```js
Expand Down
57 changes: 8 additions & 49 deletions lib/core/Axios.js
Expand Up @@ -57,61 +57,20 @@ Axios.prototype.request = function request(config) {
}, false);
}

// filter out skipped interceptors
var requestInterceptorChain = [];
var synchronousRequestInterceptors = true;
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
if (typeof interceptor.runWhen === 'function' && interceptor.runWhen(config) === false) {
return;
}

synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;
// Hook up interceptors middleware
var chain = [dispatchRequest, undefined];
var promise = Promise.resolve(config);

requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
chain.unshift(interceptor.fulfilled, interceptor.rejected);
});

var responseInterceptorChain = [];
this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);
chain.push(interceptor.fulfilled, interceptor.rejected);
});

var promise;

if (!synchronousRequestInterceptors) {
var chain = [dispatchRequest, undefined];

Array.prototype.unshift.apply(chain, requestInterceptorChain);
chain.concat(responseInterceptorChain);

promise = Promise.resolve(config);
while (chain.length) {
promise = promise.then(chain.shift(), chain.shift());
}

return promise;
}


var newConfig = config;
while (requestInterceptorChain.length) {
var onFulfilled = requestInterceptorChain.shift();
var onRejected = requestInterceptorChain.shift();
try {
newConfig = onFulfilled(newConfig);
} catch (error) {
onRejected(error);
break;
}
}

try {
promise = dispatchRequest(newConfig);
} catch (error) {
return Promise.reject(error);
}

while (responseInterceptorChain.length) {
promise = promise.then(responseInterceptorChain.shift(), responseInterceptorChain.shift());
while (chain.length) {
promise = promise.then(chain.shift(), chain.shift());
}

return promise;
Expand Down
6 changes: 2 additions & 4 deletions lib/core/InterceptorManager.js
Expand Up @@ -14,12 +14,10 @@ function InterceptorManager() {
*
* @return {Number} An ID used to remove interceptor later
*/
InterceptorManager.prototype.use = function use(fulfilled, rejected, options) {
InterceptorManager.prototype.use = function use(fulfilled, rejected) {
this.handlers.push({
fulfilled: fulfilled,
rejected: rejected,
synchronous: options ? options.synchronous : false,
runWhen: options ? options.runWhen : null
rejected: rejected
});
return this.handlers.length - 1;
};
Expand Down
93 changes: 7 additions & 86 deletions test/specs/adapter.spec.js
@@ -1,98 +1,19 @@
var axios = require('../../index');

describe('adapter', function () {
beforeEach(function () {
jasmine.Ajax.install();
});

afterEach(function () {
jasmine.Ajax.uninstall();
});

it('should support custom adapter', function (done) {
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
});
};

request.send(null);
});
}
}).catch(console.log);
var called = false;

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);
});
adapter: function (config) {
called = true;
}
}).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;
});

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() {
setTimeout(function () {
expect(called).toBe(true);
done();
});
}, 100);
});
});

0 comments on commit 8264cd0

Please sign in to comment.