简体   繁体   中英

javascript window.open from callback

window.open() called from main thread opens new tab by default.

But, here open new window every time (Opera 16 and Google Chrome 29)

<input type="button" value="Open" onclick="cb1()">

<script type="text/javascript">  
function cb1() {
    setTimeout(wo, 1000); //simple async
}

function wo()
{
   var a = window.open("http://google.com", "w2");
   a.focus();
}
</script>

(lol, this is my answer for Open a URL in a new tab (and not a new window) using JavaScript ).

How I can open in the tab (by browser default) here?

We ran across this same problem and hunted around SO for an answer. What we found works in our circumstances and the distilled wisdom is as follows:

The problem is related to browser pop-up blockers preventing programmatic window opens. Browsers allow window opens from actual user clicks which occur on the main thread. Similarly, if you call window.open on the main thread it will work, as noted above. According to this answer on Open a URL in a new tab (and not a new window) using JavaScript if you are using an Ajax call and want to open the window on success you need to set async: false which works because that will keep everything on the main thread.

We couldn't control our Ajax call like that, but found another solution that works because of the same reasons. Warning, it is a bit hacky and may not be appropriate for you given your constraints. Courtesy of a comment on a different answer on Open a URL in a new tab (and not a new window) using JavaScript you open the window before calling setTimeout and then update it in the delayed function. There are a couple of ways of doing this. Either keep a reference to the window when you open it, w = window.open... and set w.location or open with a target, window.open('', 'target_name') , in the delayed function open in that target, window.open('your-url', 'target_name') , and rely on the browser keeping the reference.

Of course, if the user has their settings to open links in a new window this isn't going to change that, but that wasn't a problem for the OP.

Like the other posts mentions the best way to do this is to first open the window and then set its location after the callback or asynchronous function

<input type="button" value="Open" onclick="cb1()">

<script type="text/javascript">

function cb1() {
  var w = window.open('', 'w2');
  setTimeout(function () {
    wo(w);
  }, 1000); //simple async
}

function wo(w)
{
  w.location = "http://google.com";
  w.focus();
}
</script>

Alternatively if you are using async await you will also have the same problem. The same solution still applies.

public async openWindow(): Promise<void> {
    const w = window.open('', '_blank');
    const url = await getUrlAsync();
    w.location = url;    
}

A further enhancement is to open the window on an initial page that provides some quick feedback either by loading a url or writing some html to that page

public async openWindow(): Promise<void> {
    const w = window.open('', '_blank');
    w.document.write("<html><head></head><body>Please wait while we redirect you</body></html>");
    w.document.close();
    const url = await getUrlAsync();
    w.location = url;    
}

This will prevent a user looking at a blank tab/window for however long it takes to resolve your URL.

如果将新窗口作为新选项卡或新实例打开,则取决于用户设置。

I was working with Nestjs and Vue3 . but I solved it using this code write here. I just took the token that was sent from the back end on the localhost:8080 . So I just slice the token and set it local storage then redirect the user to the next page. which will authorize the user to use this token . Vue 3 . This way is solved. you can improve it and make it even better. that's how I did it because I used the OAuth google-passport in the backend instead of firebase

<script>

methods: {
     googleLogin() {
      const win = window.open(
        "http://localhost:3000",
        "windowname1",
        "width=800, height=600"
      );
      const validateToken = (token) => {
        localStorage.setItem("token", token);
        this.$router.push("/GeneralPage");
        window.clearInterval(pollTimer);
        clearInterval(pollTimer);
        win.close();
      };
      const pollTimer = window.setInterval(async () => {
        try {
          let url = win.document.URL;
          let token = url.slice(22, url.length);
          if (token !== "") {
            localStorage.setItem("token", token);
            this.$router.push("/GeneralPage");
            clearInterval(pollTimer);
            win.close();
            validateToken(token);
            return;
          }
          return;
        } catch (e) {}
      }, 1000);
    },
}
</script>

This is even 'hackier' but...

If you wrap the window.open in a console.log then it will work.

console.log(window.open('https://someurl', '_blank'))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM