Synchronous Ajax - does Chrome have a timeout on trusted events?

Christopher Lörken picture Christopher Lörken · Aug 22, 2014 · Viewed 8.5k times · Source

Situation

We have a situation, where we need to onclick-open a new tab in browsers after performing an XHR / Ajax request.

We do this by setting the Ajax request to be performed synchronously to keep the context of the trusted click event and this works fine.

Problem

However, in the latest Chrome version (36), we experience popup warnings when the Ajax call has some lag... A lag of 2 seconds is enough for Chrome to display a popup warning instead of opening the tab like it is supposed to. The code itself is working, I can click that button multiple times and it works all the time until the request experiences some lag. Then I get the popup warning...

Question

Is there a timeout applied to synchronous Ajax requests during which it needs to be finished for the trusted event to still be available?

Is there any way to circumvent that? After all, the call is already synchronous and freezing everything else until the result arrives.

Thanks.

Update JSFiddle

Update: I've created a JSFiddle to demonstrate the problem: http://jsfiddle.net/23JNw/9/

/**
* This method will give open the popup without a warning.
*/
function performSlowSyncronousRequest() {
    $.ajax({
     url: '/echo/html',
     data: {delay: 2}, //JSfiddle will delay the answer by 2 seconds
     success: function(){
         window.open('http://www.thirtykingdoms.com'); //this causes the popup warning in Chrome
     },
     async: false
    });
}

Answer

risingfish picture risingfish · Sep 27, 2016

What might fix this is opening the new tab before the XHR request returns and while you are still in the trusted context. Browser tabs and windows opened via Javascript maintain connections with the parent window and can communicate back and forth.

If you open a new tab when a link is clicked, you can show a loading screen in the new window while the XHR call runs. This workflow isn't quite as clean as your original request, but it would be a viable solution with some thought. The script below is just a quick example using window.setTimeout() to simulate an async XHR request.

<html>
<body>
    <h4>
    Hello
    </h4>
    <a id="openWindow" href="">Make http call and open window.</a>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
    <script>
        (function ($) {
            var newWindow = null,
                timeout = null;

          $(document).ready(function () {
            $('#openWindow').on('click', function (evt) {
                evt.preventDefault();

              newWindow = window.open('about:blank', 'tempWindow');
              $(newWindow.document).find('body').append('<div class="loading">Loading...</div>');

              timeout = window.setTimeout(function () {
                // simulates async XHR
                $(newWindow.document).find('.loading').remove();
                $(newWindow.document).find('body').append('Done loading, here\'s your data');

              }, 5000)

            });
          });

        }(jQuery));
    </script>
</body>