2

I'm trying to detect if the user is using Windows 11 in order to serve the correct binaries when they click a download button. I've found Microsoft's suggestion for how to do this here. They suggest using the navigator.userAgentData.getHighEntropyValues function which returns a promise containing the platform version. Here is the code they suggest:

navigator.userAgentData.getHighEntropyValues(["platformVersion"])
 .then(ua => {
   if (navigator.userAgentData.platform === "Windows") {
     const majorPlatformVersion = parseInt(ua.platformVersion.split('.')[0]);
     if (majorPlatformVersion >= 13) {
       console.log("Windows 11 or later");
      }
      else if (majorPlatformVersion > 0) {
        console.log("Windows 10");
      }
      else {
        console.log("Before Windows 10");
      }
   }
   else {
     console.log("Not running on Windows");
   }
 });

My problem is that this function is asynchronous and returns a promise instead of returning the value. I don't want to have to convert all of the code I use to parse user agents for every platform in to an async function.

At first, I thought I would use await instead of using the promise like this:

let ua = await navigator.userAgentData.getHighEntropyValues(["platformVersion"])

However, this meant that I would need to make the function that contains it async. And since this same code needs to work on older browsers that don't support async and ones that do, I can't do that.

Is there a way to detect if the user is using Windows 11 without this API? Or using this API but in a way that doesn't require async?

DHamrick
  • 8,338
  • 9
  • 45
  • 62

1 Answers1

3

My problem is that this function uses es6 and returns a promise instead of returning the value.

The only "ES6" (ES2015) there is the arrow function. You can use a traditional function if you don't want to use an arrow function. The promise is provided by the platform, not the language.

I don't want to have to convert all of the code I use to parse user agents for every platform in to an async function.

You don't have to, you can do what the code you've shown does: Use the .then method. Yes, it will be asynchronous (the high-entropy information is only available asynchronously, because it may have to ask the user for permission), but it will still work on browsers that don't support async functions (provided of course they support getHighEntropyValues).

Otherwise, you'll have to fall back on parsing navigator.userAgent and that's notoriously unreliable. You'll want that anyway for agents that don't support getHighEntropyValues or users who deny permission, so you can do your best guess for the drop-down. Be sure to provide a drop-down (or similar) so the user can A) Correct an incorrect guess, and B) Download for use later on another platform.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Thanks for the answer. You're right that the arrow function being es6 isn't a problem and could easily use a legacy style function. I guess the problem that I'm trying to address is that the function is async (whether by callback or await) in a place I'd like to use that information synchronously (so I don't need to replace all of the handling code on every platform). – DHamrick Nov 23 '21 at 16:20
  • @DHamrick the limitation is that the API is asynchronous, so it cannot be used synchronously. – evolutionxbox Nov 23 '21 at 16:23
  • @evolutionxbox fair enough! Is there another API that accomplishes the same goal? Figuring out if the user is using Windows 11? – DHamrick Nov 23 '21 at 16:24
  • 1
    @DHamrick no I don't think there is. https://stackoverflow.com/questions/9514179/how-to-find-the-operating-system-details-using-javascript most answers seem to use it – evolutionxbox Nov 23 '21 at 16:25
  • This solution is still async. And it does not work in Firefox. Also, it does not work if you are not using SSL. – Daniel Marín Jun 21 '22 at 13:49
  • @DanielMarín - Nothing in the answer suggests it isn't asynchronous. It doesn't use `async` syntax, which was my read of the OP's initial concern -- not using `async` syntax because it wasn't (at that time) broadly-adopted. See the part of the answer where it says, quite clearly, that the API is asynchronous, not to mention the comments above. The API is asynchronous, so you're not going to get a synchronous solution. True, you have to be in a secure context to use that particular function as recommended by Microsoft. My view is you should always be in a secure context. It's 2022. – T.J. Crowder Jun 21 '22 at 13:54
  • @T.J.Crowder - And what about browser support? This only works in Chrome based browsers (and not even in all of them). – Daniel Marín Jun 21 '22 at 14:07
  • @DanielMarín - If you have a better solution, please post it. Above I was speaking to the issues raised by the OP around the solution from Microsoft. And I mentioned a fallback (two, actually) in the final paragraph specifically because of browser support and other issues with `getHighEntropyValues` (like needing a secure context). – T.J. Crowder Jun 21 '22 at 15:44
  • @T.J.Crowder - No reason to be offended. I'm just saying this is not a solution for the question. For two main reasons: the OP specifically asked for a solution that does not require asynchronous functions and also specifically asked for a solution that works in older browsers. – Daniel Marín Jun 22 '22 at 09:00