xhr
xhr copied to clipboard
Abandon hope of removing sync XHR from the web platform?
https://xhr.spec.whatwg.org/#sync-warning
Synchronous XMLHttpRequest outside of workers is in the process of being removed from the web platform as it has detrimental effects to the end user's experience. (This is a long process that takes many years.) Developers must not pass false for the async argument when the JavaScript global environment is a document environment. User agents are strongly encouraged to warn about such usage in developer tools and may experiment with throwing an InvalidAccessError exception when it occurs.
There are some Blink use counters for sync XHR: https://www.chromestatus.com/metrics/feature/timeline/popularity/465 (measure only) https://www.chromestatus.com/metrics/feature/timeline/popularity/472 (deprecated) https://www.chromestatus.com/metrics/feature/timeline/popularity/581 (deprecated) https://www.chromestatus.com/metrics/feature/timeline/popularity/677 (async for comparison)
This does not look at all promising. There's a slight downwards trend, but starting from >2% it's hard to see it dropping to the point where removal is possible.
Some discussion (by me) at https://code.google.com/p/chromium/issues/detail?id=392311#c17
Software developers generally don't like warnings in their terminals (or dev consoles). If they know why they shouldn't use it, they're less likely to ignore it. If warnings show up, their users are slightly more Likely to report issues with their product.
There are good reasons to remove this use pattern from the platform, so folks should not give up on the idea.
At this level of usage, it doesn't seem likely that console warning will be able to drive down usage enough so that sync XHR can be removed. If console warnings is the only tool in our tool box, I think giving up hope is appropriate.
Probably discussed to death, but if the browser can just keep its UI responsive does it really matter if a script author sometimes makes his/her page freeze by a sync call to an unreliable or slow server?
To me, this is very strange. When I click on a link to go to another page, the browser UI become unresponsive as it goes to get that page.
I have a few cases in my code that I need the browser to wait while it talks to the server using XHR. The user has just clicked a button, and is expecting a short wait.
If I can't do that call synchronously, I'll have to build an artificial approach to freeze the UI until the response is received!
I can live with a "warning" in the developer terminal, but to remove this feature from the spec is going to hurt a lot!
Timeouts can be used to ensure the UI isn't locked for too long!
@glittle, can you explain how you "need" to pause the browser? Maybe show us some code? It can't be that 98% of other developers don't have this issue, but you do. Can you explain what is so critical in the interaction with the server that the user is forced to not use the browser or the page?
In this case, the call for data is sent down a number of levels, and an answer is expected. If the server call is async, there won't be an answer returned. I can see that that sounds like a bad approach in an async world. I guess I'll have to bite the bullet and redesign each of the levels of code to use async calls, and keep the user entertained while they wait!
@glittle thanks for the additional details. Best of luck with the refactor! Your users, and local Browser Vendor, will thank you for it :)
In the slim chance you are using ES6, there are ways of keeping your code looking like it's sync, but actually running async (with generators and promises).
@hallvors yes, because the user experience of such an application sucks. Sites need to be motivated to use good practices so they don't become abandonware.
@foolip apart from the desire to remove, anyone using this also should really reconsider. Is the warning really that harmful?
@annevk this is the console warning in Blink with by far the highest usage, around 2%: https://www.chromestatus.com/metrics/feature/timeline/popularity/581
There's trade-off here, between training web developers to ignore console warnings because they happen too often and for things that aren't actually going to break, and nudging people away from sync XHR even if it will never be removed. 1% would be better than 2%, after all.
What the spec says on the topic (quoted above) goes too far, I think. I don't think sync XHR is "in the process of being removed from the web platform" and no browser will be able to throw InvalidAccessError
any time soon. If it were made a bit more tentative like "sync XHR on the main thread is bad for the user experience, browsers please show console warnings and developers please stop using it, if usage is eventually low enough maybe we'll remove it" that would be better.
Given the discussion in https://lists.w3.org/Archives/Public/public-webapps/2014JanMar/thread.html#msg232 I guess we can consider alternative wording. I think the wording was based on showModelDialog()
...
I don't think we'll see a drop off until support for FormData in Web Workers improves (currently only Chrome and Opera support it). Until then there's no real alternative for developers.
That's a connection I was not aware of, which uses of sync XHR can be replaced by FormData in Web Workers?
Well I can only speak from personal experience - I'm currently using sync XHR with FormData for a drag & drop file upload system. Async causes issues with script timeouts on the server when uploading multiple large files so I need to keep it synchronous. Web Workers seemed like the ideal solution for this but the poor support for FormData means I can't use it yet.
I'm not sure I understand, does the server timeout not result in an error event in the async case like it should? Is this to work around an implementation bug, or is there something actually broken in the specs here?
No, it's just that using async in this situation causes multiple uploads to start at (roughly) the same time, slowing the time required for each file to finish. Error events all happen (and ar received) as expected.
The spec is fine:)
Oh, so I suppose it's a matter of bookkeeping, using sync XHR saves you the trouble of keeping track of pending uploads and starting them when one is finished?
If sync XHR is taken away, what alternative mechanism are you proposing to achieve same effect. We have a javascript-streaming optimization which breaks the js into smaller pieces and loads the missing ones on demand. It has been very effective in reducing the size of js and removing unused parts (http://www.instartlogic.com/products/performance/streaming/javascript-streaming). This optimizations needs to pause the js execution until network response is received and as of now, only sync XHR can achieve this.
Browser is constantly touted as a platform that can replace even OS. In a platform scenario, there will all kinds of people offering different tools / value. Removal of sync XHR because it slows the page, assumes that the web community only consists of browser gurus and naive web developers who can shoot themselves in the foot!!
If the page is slow, google search ranking will anyways punish the page, why do you want to dumb down the browser for the rest of us?! How does this helps browser to become a true platform, and not a nanny framework for less capable programmers?!
@reshadi, this is a bug about accepting that we cannot remove sync XHR, and having the spec reflect that.
@foolip thanks for clarification. I think I miss read it. I'm glad this decision is made! :)
There are several valid and useful patterns that require the use of synchronous XHR for which there is no alternative available. This proposal of deprecating synchronous XHR and the inclusion of a warning in developer console is an unnecessary scare tactic. Yes, I understand the warning is aimed at developers who don't know better with the presumably good intention to incite action aimed at improving the "general" user experience once a page is loaded, but to smack the hands of the capable and take away a powerful tool for which there is no alternative is not an acceptable solution.
@JamesDunne, this is a bug about accepting that we cannot remove sync XHR, and having the spec reflect that.
Can we get some examples put in place for better practices designed to be as easy and simple to understand as possible, so those baby programmers this warning is meant for can actually update their code accordingly. Meanwhile put a harder to understand message for senior developers to understand that this is a false warning and XHR Sync, like Disco, will never die.
Isn't this issue handled by promises and other work on making JS itself more "asyncish"? In other words, I would consider an implementation somewhat obnoxious if it warned me against doing something like
new Promise(function(resolve, reject){
var foo = new XMLHttpRequest();
foo.open('GET', 'bar.txt', false);
foo.onload = function(){resolve(foo.responseText)}
foo.onerror = function(){reject(foo}
foo.send();
}).then( /* do the work that required waiting for the response */ );
FWIW, I think I'd vote for allowing synchronous APIs in the web platform and solving the problem with browsers being so single-threaded by focusing on that problem.
(I admit that I have not tested that code to see if browsers implement sync-xhr-in-promise the way I'd expect them to do it ;). Perhaps we should add a test or five in due course?)
@hallvors Promises are orthogonal to the issue here. The foo.send()
line in your code above produces blocking behavior, i.e. JavaScript execution will pause at that line until the request is completed, making the rest of the Promise wrapper rather pointless in terms of asynchrony.
Bugger. Well, thanks for clearing that up. Too bad.
Updates about Chromium metrics (with metric names as the box sometimes does not get set):
- https://www.chromestatus.com/metrics/feature/timeline/popularity/465 XMLHttpRequestSynchronous has gone down to ~1.57%
- https://www.chromestatus.com/metrics/feature/timeline/popularity/472 SyncXHRWithCredentials has gone down to ~0.04% in last December and staying around there.
- https://www.chromestatus.com/metrics/feature/timeline/popularity/581 XMLHttpRequestSynchronousInNonWorkerOutsideBeforeUnload has gone down to ~1.3%
Feeling relieved to know that sync XHR is going to stay!
@marcoscaceres Sync XHR is important in advertising platform, perhaps it falls in <2% cases. Here goes a practical example. Please note, I tried to make the example "readable" by changing the actual codes as it might be too specific to the domain knowledge.
--- begin example -- Current problem: Supporting 3rd party tag based demand in MoPub SDK w/o Sync XHR.
Here is how mopub javascripts/html page looks like if XYZ ad network wants to add their tag:
<script>
// XYZ script here. It adds a script tag dynamically
// in the document with the ad request url expecting a JSOONP response
// OR makes an Async XHR request.
XYZ.loadAd();
// mopub assumes, that if loadAd fails to deliver an ad,
// it should call MoPub.fail() here. so the next script won't be loaded
// or will have no effect.
// BUT, the script tag, even w/o async mode,
// will be executed after the next script tag is evaluated.
// I.e. following script tag will be executed either before or in parallel.
// there is NO way to stop the JS engine to render the next script tag
// w/o sync XHR, as far as I know.
</script>
// The following script tag is added by MoPub SDK before loading the full html page
// into the browser.
// So we don't know what is in there beforehand. We can only inspected what they added.
<script>
// It is last block, so MoPub assumes that if reached here then
// an ad is delivered.
MoPub.AdReceivedSuccess().
// if XYZ.loadAd() fails to deliver an ad and but if
// the above call is made before that, then MoPub
// will count a false impression. That is really bad for business.
</script>
--- end example ---
Hope that gives you at least one use case of Sync XHR. However, If MoPub had a better/another way e.g callback/delegate etc, Sync XHR wouldn't be needed.
But till then, in such many cases where we cannot change a big player - such 3rd party integration needs Sync XHR.
It sounds like the problem is that if MoPub.AdReceivedSuccess()
is reached it's simply assumed that the previous ad was loaded successfully. Even with all the sync XHR in the world, why would that necessarily be true?
The example is a bit too abstract to give advise about, but in principle it seems straightforward to load ads without sync XHR and only report them as successfully downloaded and rendered when they really are. Can you fill in the blanks for me?