Search code examples
javascriptpromisedetectiondeferredpopup-blocker

How to slow down the execution of code for popup blocker


I've been working on an issue with my program executing too quickly to detect whether popup is being blocked by the browser. Even with the timeout, sometimes the window that is opened doesn't get closed. I've also tried opening a window and passing a value back to the parent window and that didn't work either.

setTimeout(DetectPopUp(), 1000);

function DetectPopUp() {
  var puTest = setTimeout(window.open("", "", "width=1,height=1,top=2000"));
    
  try {
    puTest.close();
    return false;
  } catch (e) {
    return true;
  }
}

Any ideas on how to do this?


Solution

  • As already mentioned the source of the OP's currently failing code is how the OP uses setTimeout and its return value. The latter is not the handle of a window reference as the OP seems to assume but the timeout specific identifier which can be used for e.g. canceling the timeout before the execution of the to be delayed code happens.

    Thus, the OP actually does not need to write a deferred version of a popup blocker test since window.open immediately returns the result of its action which either is a Window object (no popup blocker) or is the null value (most probably due to a popup blocker).

    But of cause one could come up with promise based test functionality implemented as a single async function which then can be utilized either as chained promise or within another async function by the await operator.

    async function promisedPopupBlockerTest() {
      return new Promise((resolve, reject) => {
        try {
          const result = { hasBlocker: true }; // result default.
    
          const handle = window.open('', '', 'popup=true,width=1,height=1,top=2000');
          if (!!handle) {
    
            handle.close();
            result.hasBlocker = false; // result value change.
          }
          resolve(result); // resolve always with a valid result.
    
        } catch (reason) {
    
          reject(reason); // reject for/with whatever reason.
        }
      });
    }
    
    // ... usage as ...
    
    // ... either chained promise ...
    promisedPopupBlockerTest()
      .then(result => console.log(`resolved with ${ JSON.stringify(result) }`))
      .catch(reason => console.log(`rejected with ${ JSON.stringify(reason) }`));
    
    // ... or with async...await syntax ...
    (async () => {
      const result = await promisedPopupBlockerTest();
      console.log('awaited test result ... ', result);
    })();
    
    // prove of the popup blocking behavior of SO sandboxes.
    const handle = window.open('', '', 'popup=true,width=1,height=1,top=2000');
    console.log({ handle });