Windows must be created on the same stack (aka microtask) as the user-initiated event, e.g. a click callback--so they can't be created later, asynchronously.
However, you can create a window without a URL and you can then change that window's URL once you do know it, even asynchronously!
window.onclick = () => {
// You MUST create the window on the same event
// tick/stack as the user-initiated event (e.g. click callback)
const googleWindow = window.open();
// Do your async work
fakeAjax(response => {
// Change the URL of the window you created once you
// know what the full URL is!
googleWindow.location.replace(`https://google.com?q=${response}`);
});
};
function fakeAjax(callback) {
setTimeout(() => {
callback('example');
}, 1000);
}
Modern browsers will open the window with a blank page (often called about:blank
), and assuming your async task to get the URL is fairly quick, the resulting UX is mostly fine. If you instead want to render a loading message (or anything) into the window while the user waits, you can use Data URIs.
window.open('data:text/html,<h1>Loading...<%2Fh1>');