New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Requests unexpectedly delayed due to an axios internal promise #2609
Comments
@SashaKoro Really understand your expectation. But I am afraid that axios can't achieve that as it is a promise-based design. One workaround can be that don't write too much codes after axios calls. If possible, wrap them in another macro task.
|
@chinesedfan Hey, thanks for the quick response. To clarify further; this is not an issue solely because Looking at axios.interceptors.request.use(function (config) {
return new Promise(function (resolve) {
// do something async
setTimeout(function () {
config.headers.async = 'promise';
resolve(config);
}, 100);
}); However, not everyone leverages interceptors and creating a promise only when they are used might be a good solution that will fix this issue. (It would also be cool to sniff if the interceptor does an async operation before creating the promise; this would allow consumers to leverage synchronous interceptors without paying a penalty) I'm going to look into this further. So the issue with wrapping the rest of our code in a timeout block is that it is not just a single function (like in the example), the rest of our code is modules and modules of React and Redux code. It would also have to be handled on a case-by-case basis since we are making dozens upon dozens of different |
@SashaKoro Totally agreed with you. The key point is that the real request is send in a |
I've got a working proof of concept of a possible solution. My proposed changes revolve around creating a Promise only when necessary. It will cover the following scenarios (behavior will not change):
For all other cases*, a Promise will not be pre-emptively created and the request will be sent in a predictable manner at the time the *This is safe for response interceptors because the request can be kicked off prior to their attachment. I'm planning to get the proof of concept into a cleaner state, add comments, post a link to the branch and go over the changes in more detail. |
I've cleaned the code up. Here is the branch: https://github.com/SashaKoro/axios/tree/issue2609 The two files that have relevant changes are SashaKoro@d450b06#diff-91dcec0516f33811ee5fa71297160b3b And SashaKoro@d450b06#diff-02a02ddaa4d79e5a11b08edecfaf1e75 On that branch, I also changed |
In order to move fast on our end, we ended up forking axios with the changes I've made and deploying to production. The results have been incredible. This is our homepage before: And after: Note the timing of the requests relative to the JS execution. Prior to the change, they were all bunched up at the end of the JS execution, now the requests are being made when they are discovered in the code. Some of the requests are kicked off up to 500ms faster (this is on Chrome over broadband), on 3G connections we are seeing some requests kicked off up to a second faster. |
@SashaKoro Sure. Really appreciated for your continuous updating. I think it is one of the most annoying things in open source, especially for axios, which is famous and important, but without enough active maintainers. Your pull request is almost there, except for one or two tiny flaws, then I can give it an approval. If no one opposes it, I can even merge it (in fact, it requires more reviewers to check, as it may break the core functionalities). At last, I have no npm publish permission. The real release date still needs lots of our patience. |
@chinesedfan Hey, no problem! Totally understandable. I appreciate your feedback, I definitely missed a couple of things in the implementation. |
Hi, @chinesedfan @SashaKoro I have found similar things going around our server only application but still not confirmed on the actual cause of the delay. Please have a look at this Question if this makes sense. |
#2702 has been merged, so this can be closed I assume? Anyway, thanks for the improvement! |
Description / Context
We are using axios in production and I've stumbled onto a peculiarity recently. Most of our XHR requests are made via axios but there was one that was made by leveraging
XMLHttpRequest
directly. When looking at the request waterfall on webpagetest (a popular site for analyzing website performance), the request that is leveragingXMLHttpRequest
directly was being sent earlier than the requests leveraging axios. Here's a snippet from webpagetest showing this:Request
#46
leveragesXMLHttpRequest
directly and requests#49-54
leverage axios. The thing is: the requests are discovered in the code at around the same time. In fact, several of the axios requests are above request#46
in our code, (here is a simplified version):So the requests are discovered around the same time but the axios calls are delayed by 200-300ms (up to 1000ms in certain cases) Why this is happening is a combination of two factors; axios creating a promise under the hood (before sending the request), and the main thread being busy with JavaScript execution (represented by the pink bar extending from request
#30
). Here is a call stack of an axios XHR request (Note the Promise.then line):To Reproduce
I've got a fork of axios with a reproducable comparison here: https://github.com/SashaKoro/axios
Open your browser's devtools and navigate to
http://localhost:3000/get
. The example sends three XHR requests; one viaaxios
, one viaXMLHttpRequest
and one viafetch
. Afterwards, a long JavaScriptwhile
loop ties up the main thread. Here is the code: https://github.com/SashaKoro/axios/blob/master/examples/get/index.html If you inspect the Dev Tools (Network tab), you will see something like this:Three requests are sent, two at roughly the same time, but the third after a ~280ms delay (on my hardware) - the
axios
request! Becauseaxios
turned the request into a promise under the hood (before sending the request), the JavaScript event loop continues onward and runs thewhile
loop, which blocks the main thread and theaxios
request is delayed from getting sent.Expected behavior
The expected behavior is that an
axios
request is sent when it is discovered in the consumers code. This is the behavior of vanillaXMLHttpRequest
and theFetch
API. And this is usually the behavior in a lab like environment whenaxios
is being tested in isolation. However in a production environment where your website is doing all of the JavaScript this issue can creep up. Delayed XHR calls for critical content cause assets to be rendered later, affecting bounce rate / conversion rate and user experience.Environment:
The text was updated successfully, but these errors were encountered: