Синхронный Ajax - у Chrome есть тайм-аут на доверенных событиях?

Ситуация

У нас есть ситуация, когда нам нужно onclick - открыть новую вкладку в браузерах после выполнения запроса XHR/Ajax.

Мы делаем это, устанавливая запрос Ajax синхронно, чтобы сохранить контекст события доверенного клика, и это работает нормально.

Проблема

Однако в последней версии Chrome (36) у нас появляются всплывающие предупреждения, когда вызов Ajax имеет некоторое отставание... Для Chrome достаточно отображать всплывающее предупреждение, а не открывать вкладку как это предполагается. Сам код работает, я могу нажать эту кнопку несколько раз, и он работает все время до тех пор, пока запрос не задержит некоторое отставание. Затем я получаю всплывающее предупреждение...

Вопрос

Есть ли тайм-аут, применяемый к синхронным запросам Ajax, в течение которых он должен быть завершен, чтобы доверенное событие все еще было доступно?

Есть ли способ обойти это? В конце концов, вызов уже синхронный и замораживает все остальное, пока результат не достигнет.

Спасибо.

Обновить JSFiddle

Обновление: я создал JSFiddle, чтобы продемонстрировать проблему: 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
    });
}

Ответ 1

Что может помешать, это открыть новую вкладку до того, как запрос XHR вернется и пока вы все еще находитесь в доверенном контексте. Вкладки браузера и окна, открытые через Javascript, поддерживают соединения с родительским окном и могут взаимодействовать туда и обратно.

Если вы открываете новую вкладку при нажатии ссылки, вы можете показать экран загрузки в новом окне во время вызова XHR. Этот рабочий процесс не так чист, как ваш первоначальный запрос, но с некоторыми соображениями это было бы жизнеспособным решением. script ниже - это просто быстрый пример, использующий window.setTimeout() для имитации запроса async XHR.

<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\ your data');

              }, 5000)

            });
          });

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

Ответ 2

Привет @ChristopherLörken. Можете ли вы привести примерный код или скрипку того, что вы делаете? Возможно, я не понимаю, чего вы хотите.

Я думаю, что это поможет:
Если вам нужно событие в вашем контексте, вы можете сохранить ссылку на событие для последующего использования, например, в обратном вызове. Пример использования 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);
   });
});

Таким образом, вам не нужно вызывать запрос синхронизации для использования события в вашем контексте и, как запрос async, хром не жалуется на это.:)

Ответ 3

Ваша проблема не в XMLHttpRequest, а при delay (задержка синхронизации, возможно, ошибка в WebKit/Blink)

См. пример (http://jsfiddle.net/23JNw/32/ в Snippet не разрешает всплывающие окна):

function performSlowSyncronousRequest() {
    var endsIn, initial;

    delay = 5000;

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

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

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

Примечание: что sjax (синхронизация XMLHttpRequest) считается устаревшей некоторыми браузерами, очень плохо для пользователя.

Я попытался имитировать клик, но не работал:

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.com");
	});
}, 1000);