6 ms·
8.4% of IE9 hangs caused by not using XMLHttpRequest asynchronously
- ams6110 15y agoIn the early days of AJAX, IE actually had the best support for doing things like getting some XML data from the server and doing in-browser XSL transforms. I would often write synchronous calls when there was nothing the user could really do until the result of the call was obtained and the UI updated, as it made the code more straightforward and also IIRC the browser blocked while the transform was happening anyway.
- AshleysBrain 15y agoWhy do they run javascript on the UI thread?!
- jameskilton 15y agoExactly. Sounds like a flaw in IE 9 that they're trying to pass off as an error on the webpage. If the API / functionality exists it should work and not give you a chance of killing the browser.
- olavk 15y agoSync XHR should hang the page while waiting for the response. It should not hang the whole browser, but it should pause rendering and event processing on the page - i.e. cause the page to be unresponsive. Otherwise it wouldn't be synchronous. A different issue is whether the synchronous mode of XHR was a good idea in the first place. But what's done is done.
- nkassis 15y agoIt's not a flaw in IE it's the same in all browsers they use one thread for javascript and UI updates. IE10 will have Web Workers which can be used to prevent this but using Web Workers still involves programmers making their code work async which is the point of this post.
- Hov 15y agoWhy does who run js in the UI thread? As far as I know, every browser will exhibit this behavior. I haven't tested it though. How do you propose easily marshalling js events back to the UI thread if you ran it on a separate thread?
- olavk 15y agoThis is how it is supposed to work. JavaScript is single-threaded, and JavaScript execution pauses rendering and event-processing on the page. A synchronous XHR request is just like any other long-running JavaScript: it blocks the UI.
- pornel 15y agoThat's direct consequence of how JS/DOM is designed to work. IE is not the only browser that has UI thread tied to JS execution. Although browser chrome could run in a separate thread, that wouldn't prevent page itself (and any interaction with it) from "freezing". This is because any interaction with the page is fired as JS events, and if JS is busy, it can't pick those events. Browser can't react to any clicks (even links and buttons can't be activated, because JS is given chance to intercept and cancel those clicks). Even if you want to leave the page, beforeunload/unload events will get queued. Also pages need to be refreshed only between JS events (that's how DOM animation works, that's how canvas buffering is specced), so even screen redraw is tricky when JS is executing.
- AshleysBrain 15y agoBut shouldn't the page at least run in its own thread (or process)? If Javascript hangs, sure the page can hang, but the browser UI should still work and give you the opportunity to terminate or recover. According to TFA, Javascript blocks the UI thread in IE9. Their own guidelines that they link to [1] says "Do not: call into any 'unknown' code from your UI thread". I don't see why a browser is special and can't keep to that rule - especially a modern browser like IE9. [1] http://msdn.microsoft.com/en-us/library/dd744765(v=vs.85).aspx http://msdn.microsoft.com/en-us/library/dd744765(v=vs.85).as...
- justsomedood 15y agoBy the UI they mean the controls inside of the page, not the browser's UI - your back, refresh and other browser controls still work. The same thing happens if you have javascript that consumes CPU and doesn't return for a long period of time. While the javascript is running controls on the page don't work such as buttons and select lists, but when the javascript finishes the UI thread regains control and responds to input again.
- pak 15y agoHow would JavaScript be able to override default event handlers if it weren't tied to the UI thread? Synchronous XHR will tie up every other browser too--because it's a blocking call, hence the "synchronous"... A rare example of appropriate use is an onbeforeunload handler that saves your work on a webpage when you close the window, because in this case, asynchronous calls will never complete between the click and the window unloading so you have to synchronously block the unload event handler. Now, go post that on this SO thread [1] and make some points ;-) [1] http://stackoverflow.com/questions/2088318/is-there-any-reason-to-use-a-synchronous-xmlhttprequest http://stackoverflow.com/questions/2088318/is-there-any-reas...
- AshleysBrain 15y agoDoesn't Chrome run javascript in its own process for each tab's page? How do they handle overriding default event handlers? Or am I misunderstanding something?
- pak 15y agoChrome runs a separate process for each tab, and that process includes the layout engine and the JS engine (V8) running in tandem. V8 has to be able to block the layout engine from rendering, otherwise it will draw invalid page states. The execution model (greatly oversimplifying) is that the browser runs a tight loop that monitors for changes to the DOM state and input events, and then synchronously executes JS code bound to these events (and the native handlers if they are not overridden), finally re-rendering parts of the viewport that become "dirty". In a browser that isolates tabs into their own processes, like Chrome, try opening a tab for www.google.com and then enter this in your address bar: javascript:document.getElementById('lst-ib').onclick=function(){while(1);} When you click on the search box the entire tab will freeze, because the tab process is stuck inside the JS engine running the infinite loop function we bound to the click handler. It's not a matter of bad browser design, that's how the JS execution model is intended to work. "Web workers" is the HTML5 proposal for running JS code that does not block the event loop. They do not have direct access to the DOM and can only communicate with JS code in the main event loop via a message passing API.
- 15y ago
- deleted 15y ago[deleted]
- unfletch 15y agoFor people who only read as far as the "Fixing It" section, this post will make the problem worse. There's an unfortunate mistake that changes the meaning to the exact opposite of what was intended: Write your code to call open asynchronously. You need to pass false for the bAsync parameter to the open method... The "bAsync" parameter governs whether the call will be async. True (the default) means async, not false. Oops. At least the examples get it right.
- bstar77 15y agoI personally have not had a need to use XMLHttpRequest in my 5 years of js development, so I find it very strange that it accounts for 8% of hangs in IE. Is there some design pattern MS devs use in javascript causing this problem? Pretty much every JS framework encourages async requests and managing deferred objects. Also, why are people still doing JS calls inline and not at the bottom of the page... or at least on domloaded? I don't think XMLHttpRequest specifically is the problem, sounds more like a multitude of poor coding practices that create blocking situations.
- olavk 15y agoAnother commenter has a legitimate use case for a synchronous XHR: http://news.ycombinator.com/item?id=2846258 http://news.ycombinator.com/item?id=2846258 Regarding bottom on page, domloaded event etc. - that does not change anything, the js is still executed synchronously.
- cpeterso 15y agoHavoc Pennington wrote recently about synchronous and asynchronous APIs, with an interesting analysis of the differences between (synchronous) callbacks and (asynchronous) events. He suggests that a callback should be either always sync or always async, as a documented part of the API contract. Callbacks, synchronous and asynchronous: http://blog.ometer.com/2011/07/24/callbacks-synchronous-and-asynchronous/ http://blog.ometer.com/2011/07/24/callbacks-synchronous-and-...