Ughy23
Ughy23

Reputation: 23

Javascript wait for window to close before opening another

I need to open a series of popup windows, each window must be closed before the next one can be opened.

function openWindows() {
    var urls = getListOfUrls();
    
    for (let url of urls) {
        openWindow(url);
        // Wait for window to close before continuing.
    }
}

The only way I found to make sure that a window is closed is to use a setInterval which, as I understand it, causes the function behave asynchronously.

Any idea on how I can achieve this?

Upvotes: 2

Views: 1538

Answers (1)

jsejcksn
jsejcksn

Reputation: 33730

Potential alternate suggestion

Without more information, it sounds like what you're trying to accomplish can be completely automated using puppeteer and in-page scripting. If the URLs that you are visiting aren't all in the same origin, then this is the only method which will work (the solution below will not apply).

Interpretation of question

However, let's say that you need to manually perform some tasks on each page in order (one at a time) for whatever reason (maybe the pages you're retrieving often change their DOM in a way that keeps breaking your scripts), but you want to skip the rigor of serially opening the URLs in new tabs, so that you can just focus on the manual tasks.

Solution

JavaScript web APIs don't provide a way to check for the closure of a window (a script would no longer be running at that point), but the last event that you can respond to is the unload event, and using it would look something like this:

References:

async function openEachWindowAfterThePreviousUnloads (urls) {
  for (const url of urls) {
    console.log(`Opening URL: "${url}"`);
    const target = '_blank';
    const initialTime = performance.now();
    const windowProxy = window.open(url, target);

    if (!windowProxy) {
      throw new Error(`Could not get window proxy for URL: "${url}"`);
    }

    await new Promise(resolve => {
      windowProxy.addEventListener('unload', ev => {
        const delta = performance.now() - initialTime;
        const thresholdMs = 1000;
        if (delta < thresholdMs) return;
        resolve();
      });
    });
  }
}

const tags = [
  'javascript',
  'puppeteer',
];

const urls = tags.map(tag => `https://stackoverflow.com/questions/tagged/${tag}`);

openEachWindowAfterThePreviousUnloads(urls);

Code in TypeScript Playground

Caveats:

The script will fail if any of the following is not true:

  • Every URL is in the same origin as that of the invoking window

  • If your browser blocks pop-ups, the page where you run the script is allowed to create pop-ups. Example error:

    pop-up blocked


You can try the code above in your browser JS console on this page, and (as long as https://stackoverflow.com is allowed to create popups) it should work.

Upvotes: 2

Related Questions