whatwg / xhr

XMLHttpRequest Standard
https://xhr.spec.whatwg.org/
Other
314 stars 129 forks source link

Abandon hope of removing sync XHR from the web platform? #20

Open foolip opened 9 years ago

foolip commented 9 years ago

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.

foolip commented 8 years ago

It's not merely a cosmetic concern, if the user is on a bad network the whole tab can freeze for a long time.

Everyone I know who works on the web platform takes compat and interop very seriously, but they're not the only concerns and don't always trump all others. I don't know how sync XHR will work out, it can't be removed right now at least. I kind of doubt the deprecation is going to help drive down usage much, which was the point of this issue to begin with.

BourgeoisBear commented 8 years ago

Thanks for hearing me out Philip.

I-Maps commented 8 years ago

If you use XHR with jQuery.getScript to load a JavaScript file there can be timing issues when the page loads. The simple solution that works is to set async to false. Why ruin such a simple solution? Why do away with this method and have people worry about finding alternatives when the working method already exists?

bedney commented 8 years ago

So I'll chime in here with the standard response that I always tend to leave whenever I see articles and issues on the Net having to do with removing some already standardized feature based on 'metrics' or 'instrumentation' and watching pages fly by on the public Internet. Google has done this for a while and now Microsoft has taken up the practice as well.

At first blush, this sounds like a great idea. The problem is that almost everyone involved is looking at the public Web (probably because they work at companies that only do public Web work). The problem is that there are literally millions of web pages behind corporate/organizational firewalls that no search engine will ever see - ever. I work very closely with developers of internal corporate web applications whose app will never see the light of day outside of their org.

These developers use features that the W3C or the originator of the technology told them were standardized long ago. The effort to rework these applications to accommodate removal of these features are staggering in terms of both time and money. Sync XHR is one of those features.

My opinion, which I've expressed elsewhere, is that the Web needs to a purely additive platform, at least in terms of technologies that have been standardized by either the W3C, WHAT.org or (in a few cases before these organizations existing or had the force behind them) an ad-hoc standard.

Putting a deprecation warning might make folks here feel better, but it isn't really going to change the reality of all of those Web apps that no one can ever 'see' that contain code written long ago by developers that have long since left the project that will break when changes like this are implemented.

saschanaz commented 7 years ago

but together with a more active plan to get rid of this, the deprecation message could still make sense

If we want really be aggressive probably browsers can forcefully block n seconds whenever sync XHR occurs and irritate users so that devs will actively remove it. Not sure browsers may do it. 🤔

This way the sync XHR won't break but the user experience will break, which is similar with the Flash deprecation thing.

domenic commented 7 years ago

One thing we've talked about in Chrome is measuring how many uses of sync XHR are in third-party iframes (often ads) vs. top-level pages; if the majority is in third-party iframes then we may be able to disable it more aggressively. @ricea and @tyoshino were planning to look into that sometime, I believe.

BourgeoisBear commented 7 years ago

What are the obstacles to having stronger versioning facilities? By versioning, I mean having a way to specify a compatibility level that implies an agreed upon set of API features. If we developers had some way to specify compatibility requirements, the browser could either swap JS engines, or at least give a meaningful error to the user that the code they are trying to run is outdated.

It would also reduce the need for Rube Goldberg feature detection schemes like this one: http://stackoverflow.com/questions/29046635/javascript-es6-cross-browser-detection

ricea commented 7 years ago

We have an action item to add metrics to Chrome with the aim of splitting Sync XHR by use case and then knocking out one use case at a time.

We also discussed some ideas for identifying where Sync XHR is used via a framework such as older versions of jqeury. Anecdotally it appears this inflates usage stats quite a bit.

Something that bothers me is that we can certainly drive down usage by 9X% but we only get the technical payoff if we get usage down to 0.

reshadi commented 7 years ago

As many have already mentioned, there are rare, but legit use cases for sync xhr that have no alternative solutions as of now. In an ideal world, everything, including browser api, will be async. But until then, and during transition, there should be possibly dangerous or unsafe solutions for real world cases.

I have been involved in optimizing other people's applications for a long time. In many cases, even if the app developers want to follow best practices themselves, they cannot easily influence the behavior third party libraries they need. Which makes transition to better api very hard.

What I have noticed in most cases is this: although the JS itself is single threaded, it still sometimes need to synchronize with external events. In a web app, we run into a lot of non-deterministic elements such as state of the browser cache, network behavior, user behavior ...; which make optimizations hard.

In general, we can have aggressive solutions that rely on common case scenarios, but have a fall back mechanism for correctness. In these cases, we need a mechanism to pause the execution of the JS "without unwinding the whole call stack" and un-pause when some event happens. This is equivalent to the necessary evil "wait-on" mechanism in other languages or platforms. To discourage casual usage, we can make it hard to use, e.g. require explicit api for taking a snapshot of call stack, and then explicitly restoring it at the beginning of the event handler.

As of now, sync XHR is the only available mechanism for simulating this behavior. Unfortunately, the "wail-on" feature of sync XHR is mixed up with network activity. I think if these two were separated, a lot of current legit use cases for sync xhr would go away, or can be re-implemented with some effort.

I-Maps commented 7 years ago

I have been developing WebGIS mapping applications for 20 years. Over the last ten years, I have developed a technique that requires javascript code to be loaded with synchronous XHR in the head of the document before the maps are initialized in the body onload event. Synchronous XHR is the only method I have found that works for this technique. I have developed mapping applications using this technique for numerous clients that serve thousands of people per day. Over all these years, no one has ever complained that my interactive mapping applications that use the synchronous XHR technique have locked up their browsers.

Several of my projects have been long-term development projects that have required large investments of my own time and money. I am wondering if the people who are complaining about synchronous XHR have ever run their own companies and invested something like a year of work and $100K of their own money in a project that relies on synchronous XHR. If they did, they might not be so enthusiastic about eliminating it.

The people who want to kill synchronous XHR seem to ignore others who say they have legitimate and necessary uses for it and have large time and money investments in projects that rely on it.

The only complaint I see here is that some programmers use synchronous XHR incorrectly or use it where it is not required and that incorrect use can cause problems with a client's browser. I have never encountered this issue with any site. I have never heard anyone say anything about it except for the people complaining here, so it is apparently not a significant or widespread problem.

If you want to put out a warning message that says "Synchronous XMLHttpRequests may have detrimental effects on the end user's experience, please be sure you are using it correctly", that would be OK, but to use the deprecation message to try to kill it's use appears to be a misguided effort that would be detrimental to web programming technology and businesses that have large investments in projects that rely on synchronous XHR .

I hope that other legitimate users will also encourage the abandonment of this effort.

BourgeoisBear commented 7 years ago

@I-Maps, it seems like most of the push for this is coming from Google & Mozilla due to the impact that abuse of sync XHR has on requestAnimationFrame(), which probably has substantial dollars-and-cents consequences for their businesses. Since they can't fix sloppy coding on the 3rd-party pages that host the ads, killing the pain-point in the API is probably their best bet.

I suspect most of the web application developers complaining here are largely being talked-past because we at least have control over our own code, and most of us aren't supporting browser development in any meaningful way, so why should they care?

nicolashenry commented 7 years ago

@I-Maps

a technique that requires javascript code to be loaded with synchronous XHR in the head of the document before the maps are initialized in the body onload event

I am curious, why don't you just initialize your maps in the xhr load callback (and wait that the document is ready) instead ?

You could do something like :


var loadPromise = new Promise(function(resolve) {
    window.addEventListener('load', resolve, true);
});

var req = new XMLHttpRequest();

req.onreadystatechange = function(event) {
    if (this.readyState === XMLHttpRequest.DONE) {
        if (this.status === 200) {
            var mydata = this.responseText;
            loadPromise.then(function() {
                initialize(mydata);
            });
        } else {
            console.log("Error: %d (%s)", this.status, this.statusText);
        }
    }
};

req.open('GET', 'http://myapi.com', true);
req.send(null);
I-Maps commented 7 years ago

I tried goofing around with the Promise technique before without success.

I am passing ASP data through the web page to the ASP - JS page that needs to be there, but I suppose I could pass the data through the URL in the XHR call.

It is a lot easier to use one line to call the code synchronously in the head of the page and then pass the ASP data in the onload event.

<script language="JavaScript">$.ajax({type:"GET",url:"code.asp",dataType:"script",as ync:false})

Using ajax to load the ASP-JS page may seem unnecessary, but I have my reasons for it.

People are saying the browser will hang if the requested resource is not there. In this case, the web page and the js page are coming from the same place. If the server was down, the web page wouldn't load in the first place.

This has worked for 10 years with no problem.

As they say - "If it's not broke, don't fix it". So, unless the folks who are trying to change this succeed, I will leave it as is.

nicolashenry commented 7 years ago

@I-Maps

<script
language="JavaScript">$.ajax({type:"GET",url:"code.asp",dataType:"script",as
ync:false})</script>

Why not doing this instead ? : (I don't know how to get a timestamp with ASP)

<script src="code.asp?_=<%= timestamp() %>"></script>

From what I understand, it should do the same thing.

I-Maps commented 7 years ago

I don't know about that either. I've never seen anything like that.

There is a timing issue with the code and the related objects on the page also, so it's complicated

Anyway, thanks for the suggestion.


From: "Nicolas HENRY" notifications@github.com Sent: Monday, May 29, 2017 4:42 PM To: "whatwg/xhr" xhr@noreply.github.com Cc: "I-Maps" phillips@i-maps.com, "Mention" mention@noreply.github.com Subject: Re: [whatwg/xhr] Abandon hope of removing sync XHR from the web platform? (#20)

@I-Maps

Why not doing this instead ? : (I don't know how to get a timestamp with ASP)

From what I understand, it should do the same thing.

- You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

ricea commented 7 years ago

I just spent a couple of days debugging a problem in a major piece of enterprise software caused by use of sync XHR. Let me assure you, it does cause problems for real-world applications. Expensive problems. Chrome has a long history of hacks aimed at mitigating the problems. Even if you think you know what you're doing, you're actually relying on hacks that make it mostly work mostly well enough most of the time.

emahuni commented 7 years ago

I was going through this whole discussion to point where i thought adding my 2 cents worth is right. I think this message about deprecation and the actual deprecation should just be removed. Browsers should be coded not to freeze over this simple issue. I have never seen browser source code before to know what's going on in there, but I think this should be solved in the browser js engine not in the scripts being run. I was thinking why not multi-thread the browser? There are situations that cannot be solved with async/promises etc at all. consider this;

An app loads its scripts through webpack and some through async calls as required during runtime. The app wants to load a settings script from the server and those settings are to be used by various areas of code almost immediately after the settings request has been done. The catch is that this settings file cannot and shouldn't be bundled up into the webpack bundle file since these are settings that can be changed by other clients during runtime, then when the app reloads next time it has to use those new settings. Most of this code is modular and cannot be put in a single resolve function of promises as js would have just moved on deeper into the code. However, letting the code continue further without waiting for the settings will break it as there is no way of telling when the settings will arrive from the server. The only way is to wait for the response and then continue or throw an error after a timeout (because this file has to be there and exactly when needed)... hence sync XHR.

This is a scenario I have faced and was actually looking for another solution offered by anything else outside of sync XHR. I tried refactoring the code several times using promises and most other methods and they never worked as effectively and simple as sync XHR requests. Throughout the code there is use of promises, async ... await, generators etc, but they don't work for this one scenario in the codebase. By trying to use these other methods has proven wasteful of valuable time and effort on unnecessary complicated and unsatisfactory trials, meanwhile knowingly ignoring the only solution that works perfectly without the detrimental effects being reported in the console.

So I am wondering why this would be removed at all. The page works fine without any detrimental effects as in the doomsday warning message being thrown in the console.

To my point of view, if this problem is inherent of javascript, then the language is poorly designed, and removing this simply makes it worse. Async await is actually a way of trying to mitigate this, howbeit, it encapsulates the code in a function again, which is the same as promises. I think the people who threw this in were actually trying to solve this, but i don't know how or where they lost it. They ended up doing the same this over. I don't think there is anything you can do with async await that you can't do with regular promises... But there is one thing you can't do with promises that you can do with sync XHR and that's wait for a response from the server before you continue with execution.

littlebee commented 7 years ago

I have heard the arguments, some religious, and up until a few months ago, I would have agreed that there really isn't a need for async: false. But then in the process of removing the last entanglement requiring server rendering of the base DOM and layout by PHP for the app I work on, I happened upon a very real use case.

During my app's initialization it uses an XMLHttpRequest with async:false to pause all scripts from loading while it fetches application options and current user context information. This information was previously bootstrapped into the page by the php layout and much of the UI code uses information in the context data in static initializers or other ways that assume it is available at time of script load.

I've tried reworking the code to make the api call to get the context information async and then dynamically generate script tags to load the remaining scripts that depend on this data being set. The result was much slower page load times stemming mostly from the browser not caching the scripts loaded via dynamically generated script tags. :(

I sure hope that it's just an idle threat to remove async:false.

BTW, I also think it's just a little pretentious to assume that you understand my user's experience needs better than I do. Just a little.

ricea commented 7 years ago

@littlebee Would it be possible to format the options and context as Javascript, so that you can use a Githubissues.

  • Githubissues is a development platform for aggregating issues.