As we all know, it’s ok to open a new window by clicking the button or a TAB event that triggers window.open. However, if some asynchronous requests are made in the click event before going to window.open, it will be blocked by some browsers, as shown in the figure below. The reason is that the security policy of the browser is matched. In the view of the browser, the opening of the window is not caused by the user’s direct operation, and it may be an advertisement or other content that the user does not want to see. So are there any ways to avoid interception? Here are some of the solutions I tried to solve the problem.

Scenario 1 simulates the a TAB click event (which will still be blocked by some browsers)

The code is as follows:

// Simulate the a TAB click event
function newWin(url) {
  const a = document.createElement('a');
  a.href = url;
  const event = new MouseEvent('click');
  a.dispatchEvent(event);
}

// After an asynchronous request, the a label click event is triggered
axios.post('xxxx', {
  a: '1'
}).then((res) = > {
  const { url } = res;
  newWin(url);
})
Copy the code

This solution does not solve the browser blocking problem, and the root cause of the click event is not the user.

Scheme 2 firstwindow.openOpen a blank window and fill it after asynchronous returnurl

The code is as follows:

// Open a new blank window
const winRef = window.open(url, '_blank');
// XXX is the title of the newly opened window. If it is not set, the title of the new window will appear temporarily "no title".
winRef.document.title = 'xxx';

axios.post('xxx', {
  a: 'a'
}).then((res) = > {
  const { url } = res;
  // Set the new window address to the URL
  winRef.location.href = url;
})
Copy the code

This solution works in person and solves browser interception problems, but during asynchronous requests, a blank page appears in a newly opened window, which is not very user friendly.

So is there a better alternative?

When looking through the data, I found that some browsers triggered the blocking according to whether window.open was triggered within 1 second after the user clicked the event. Based on this, setTimeout 1s can be set to trigger window.open to reduce the white screen time of the new blank window, that is, plan 3.

SetTimeout is used together with window.open to open blank pages

let winRef;
let targetUrl;

/ / 1000 ms delay
setTimeout(() = > {
  winRef = window.open(targetUrl, '_blank');
  winRef.document.title = 'xxx';
}, 1000);

axios.post('xxx', {
  a: 'a'
}).then((res) = > {
  const { url } = res;
  // Check whether winRef has a value, if so, a new window has been opened, then set the address of the new window to the URL
  // Otherwise assign the URL to targetUrl
  if(winRef) {
  	winRef.location.href = url;
  } else{ targetUrl = url; }})Copy the code

The maximum delay time in the code is 1000ms. If it is greater than this time, it will still be blocked. However, if the actual time of the asynchronous interface is less than 1000ms, set the time as required. This solution works in chrome, Firefox, Safari, and 360.