2

The problem with new URL(), and how URL.parse() fixes that | Kilian Valkhof

 1 week ago
source link: https://kilianvalkhof.com/2024/javascript/the-problem-with-new-url-and-how-url-parse-fixes-that/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

The problem with new URL(), and how URL.parse() fixes that

Kilian Valkhof

Building tools that make developers awesome.

Search term

The problem with new URL(), and how URL.parse() fixes that

Javascript, 24 April 2024, 3 minute read

As someone building a browser I need to parse a lot of URLs. Partially to validate them, but also to normalize them or get specific parts out of the URL. The URL API in browsers lets you do that, but it’s ergonomics aren’t ideal.

The problem with new URL()

The “new” in front of new URL() indicates that it’s used as a constructor: calling it creates a new URL instance for you. When you give it a malformed URL however, one that it can’t parse, it throws an error. Because it throws an error, you need to write code to handle that error.

If you don’t do that, The thrown error won’t get handled and your JS stops being executed. The following code looks great but if urlstring is malformed, it will stop execution:

const urlstring = "this is not a URL";
const not_a_url = new URL(urlstring);

So you'll want to wrap it in a try...catch so that the error is caught.

const urlstring = "this is not a URL";
let not_a_url;

try {
   not_a_url = new URL(urlstring);
} catch {
  // not_a_url is already undefined so no need to actually do anything.
}

That's a lot more lines of code, has more visual noise and it means you have to change not_a_url from a const to a let to be able to overwrite it. The control flow of the application ends up being more complex.

Making it slightly better

A recent addition to the URL api is URL.canParse(), a function that returns true if the URL is a parseable URL.

It's only been available cross-browser since December 2023 so it might be a little too early for general use, but it does make the code more readable.

Instead of trying and catching the error, we can first check if the URL is parseable before parsing it, and we can do that inline:

const urlstring = "this is not a URL";

const not_a_url = URL.canParse(urlstring) && new URL(urlstring);

This makes not_a_url a const again, and is definitely easier to understand.

Complaining

Rather than being constructive and writing my own little function to abstract that try...catch or canParse away from my regular code base, I decided to do the right thing and complain on Twitter:

Making new URL() throw when you give it an invalid URL was a terrible API choice.

Not much later Anne van Kesteren replied with a link to a GitHub issue discussing the addition of a "parse" function to URL that would not throw.

Anne added that issue in 2018 but my tweet renewed interest. Not much later, Anne added URL.parse() to the spec and implementation bugs were filed for all browser engines.

Anne himself implemented it in WebKit and it's also going to ship in Chromium 126 and Firefox 126.

Using URL.parse

With URL.parse we can go back to that original example all the way up top, and keep our control flow as simple as possible:

const urlstring = "this is not a URL";

const not_a_url = URL.parse(urlstring);

The browsers with this feature will ship in the next few months (Firefox in May, Chrome in June, I've not been able to figure out when Safari will) so you'll have to wait a little before using it but I can't wait to get rid of all my try..catch calls!

Hi, I'm Kilian. I make Polypane, the browser for responsive web development and design. If you're reading this site, that's probably interesting to you. Try it out!

Related Posts

Creating files in JavaScript in your browser
19 May 2020, 3 minute read

Did you know you can create files using JavaScript right inside your browser and have users download them? You can create files with a proper name and mime type and it only takes a few lines of code.

Supercharging number inputs
11 August 2020, 6 minute read

The number input type provides a nice way for to deal with numbers. You can set bounds with the min and max attributes and users can press up and down to go add or remove 1, or if you add the step attribute, go up or down by a step. But what if we want […]

Detecting media query support in CSS and JavaScript
13 July 2021, 5 minute read

Recently I needed a way to detect support for a media query in CSS and Javascript. To detect if a browser supports a certain CSS feature, you can use @supports () { … }, but that doesn’t work for media queries. In this article I’ll show you how you can detect support for media queries […]


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK