Skip to content
Advertisement

Using window.open in an async function in Firefox and Safari

The application I work on integrates with some platforms with some strict security policies when it comes to user authentication, and as such authentication from our side has to be handled a bit differently as well. The details here aren’t terribly important.

I’m working on a new feature now where a user can open some items from a list, but from a UX perspective it would make the most sense to open these up in new tabs, since users will want to open a lot of them at once without having to navigate back to the list and find their place within it again.

So to get this working, our API has a redirects endpoint that handles the authentication. Implementation details aren’t important, it’s just important to know that this endpoint will receive a URL that should be navigated to (supplied from our UI), and it’ll spit back out a redirect URL with a token.

As such, I’ve gone with the following function which gets called when a button is clicked by the user

async function openInNewTab() {
  // $ajax is an axios instance that calls the endpoint
  const { url } = await $ajax.post('/redirects', {
    data: {
      url: "myurl.com/route/to/go/to",
      //...
    }
  });

  window.open(url)
}

As you can see, it’s very simple, it gets the redirect URL from our API and tries to open that URL in a new tab. This works in Chrome, however it doesn’t work in Firefox or Safari, prompting the user that a popup was blocked.

I’m well aware that browser have a number of rules regarding popups and when they’re blocked, however in this instance this action is being initiated by user interaction via a button click, the only problem being that the function getting called is asynchronous.

Is there any way to make this work in Firefox and Safari? The function simply doesn’t work well enough in realistic network speeds without it being asynchronous, and with the way our application works there’s no way for us to circumvent the redirect URL with something like a target="_blank" in a link, that would fail to authenticate properly.

Advertisement

Answer

There’s 2 potential workarounds that I ended up with here.

They’re both fairly similar, however from my testing it seems Safari is the strictest when it comes to parsing events as popups.

The one that works in all major browsers (Chromium-based ones, Firefox and Safari), but feels a bit hacky.

Found this here: https://stackoverflow.com/a/70463940/8610114

const { url } = await $ajax.post('/redirects', {
  data: {
    url: "myurl.com/route/to/go/to",
    //...
  }
});

setTimeout(() => {
  window.open(url, "_blank");
});

And the other solution, although this one doesn’t seem like it works in Safari consistently, as it gets blocked sometimes (seemingly randomly)

const newWindow = window.open('about:blank', '_blank');

const { url } = await $ajax.post('/redirects', {
  data: {
    url: "myurl.com/route/to/go/to",
    //...
  }
});

newWindow.location.href = url;
User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement