最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

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

programmeradmin3浏览0评论

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: /

/**
* 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(''); //this causes the popup warning in Chrome
     },
     async: false
    });
}

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/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.'); //this causes the popup warning in Chrome
     },
     async: false
    });
}
Share Improve this question edited Oct 17, 2014 at 16:33 Christopher Lörken asked Aug 22, 2014 at 11:38 Christopher LörkenChristopher Lörken 2,77020 silver badges17 bronze badges 4
  • Any luck fixing this? I am experiencing the same issue and have determined the timeout to be 1000 ms. Everything above that results in a block from Chrome. – Alexander Commented Sep 9, 2014 at 16:48
  • A sync request blocks the JS execution, so the warning you're seeing is probably saying yout script is not responding. If the request wait to much for a response, you gonna see this warning. Try do a async request and on the success callback enable the button to open the tab. – Rubens Pinheiro Commented Oct 13, 2014 at 17:41
  • 1 @Rubens: Thanks for your ment, but: No. The warning is a clear popup warning just as I have desribed in my question. Furthermore, disabling and enabling the button would require two clicks by the user to open the popup which is of course easy but not what we want. We want to do a background request and open a popup with a single trusted event. – Christopher Lörken Commented Oct 15, 2014 at 17:49
  • I'm understating now, thanks for the fiddle. Well, it's hard to say, maybe Chrome turn the function context untrusted if the script wait too long to response. I'll try to find some way out for this problem :) – Rubens Pinheiro Commented Oct 17, 2014 at 18:33
Add a ment  | 

3 Answers 3

Reset to default 6

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 municate 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./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>

Hello @ChristopherLörken. Can you give a example code or a fiddle of what are you doing? Maybe I'm not understanding what you want.

I think this will help:
If you need the event in your context, you can save the reference of the event for posterior use, like in a callback. Example using jQuery:

$(myBtn).click(function(ev){
   var event = ev; //Save the event object reference
   $.ajax({
   // ... your options
   success: function(res){
     //do stuff with the event in the callback
     console.log(event);
   });
});

In this way, you don't need call a sync request to use the event in your context and, as a async request, chrome don't plain with that. :)

Your problem is not with XMLHttpRequest, but with delay (sync delay, maybe bug in WebKit/Blink)

See example (http://jsfiddle/23JNw/32/ sandbox in Snippet don't allow pop-ups):

function performSlowSyncronousRequest() {
    var endsIn, initial;

    delay = 5000;

    endsIn = new Date().getTime() + delay;

    for (; endsIn >= new Date().getTime();) {}//Delay
    window.open('http://www.thirtykingdoms.');
}

<button onclick="performSlowSyncronousRequest()">Test case</button>

Note: that sjax (XMLHttpRequest sync) is considered obsolete by some browsers is very bad for the user experience.

I tried simulate click, but not work:

function clickFire(evt){
	var el, evtFake, pos;

	el = document.createElement("a");
    el.href = "javascript:void(0);";
    el.innerHTML = "test";
	el.onclick = evt;

	document.body.appendChild(el);

	pos = el.getBoundingClientRect();

	evtFake = new MouseEvent("click", {
		bubbles: false,	
		cancelable: false,
		view: window,
		detail: 0,
		screenX: window.screenX,
		screenY: window.screenY,
		clientX: pos.left + 1,
		clientY: pos.top + 1,
		ctrlKey: false,
		shiftKey: false,
		altKey: false,
		metaKey: false,
		button: 1,
		buttons: 0,
		relatedTarget: el
	});
	el.dispatchEvent(evtFake);

	window.setTimeout(function() {
		document.body.removeChild(el);
	}, 1);
}

window.setTimeout(function() {
	clickFire(function() {
		window.open("http://stackoverflow.");
	});
}, 1000);

Note: The web browsers are very smart today and we will hardly get cheat them.

Solution

Don't use pop-ups ( I hate pop-ups :) ), try simulate "pop-up" using <iframe>: http://demos.jquerymobile./1.4.0/popup-iframe/

Or add um button using modal (like bootstrap) and and place a message asking the user clicks:

<script src="https://ajax.googleapis./ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//maxcdn.bootstrapcdn./bootstrap/3.3.2/js/bootstrap.min.js"></script>
<link href="//maxcdn.bootstrapcdn./bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet"/>

<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
        <h4 class="modal-title" id="exampleModalLabel">New message</h4>
      </div>
      <div class="modal-body">
         Open pop-up :)
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
        <button id="popupIsNotPopular" type="button" class="btn btn-primary">Ok</button>
      </div>
    </div>
  </div>
</div>

window.setTimeout(function() {
    $('#exampleModal').modal();
}, 2000);


$("#popupIsNotPopular").click(function() {
    window.open("http://www.stackoverflow.");
});
发布评论

评论列表(0)

  1. 暂无评论