我们需要在执行XHR / Ajax请求后 onclick-在浏览器中打开一个新标签。
我们通过将Ajax请求设置为同步来保持受信任点击事件的上下文,这样做可以正常工作。
但是,在最新的Chrome版本(36)中,当Ajax通话有一些延迟时,我们会遇到弹出警告...... Chrome的2秒延迟就足以让Chrome显示弹出警告而不是打开标签就像它应该的那样。代码本身正在工作,我可以多次单击该按钮,它一直有效,直到请求遇到一些延迟。然后我得到弹出警告......
是否有超时应用于同步Ajax请求,在此期间需要完成它以使可信事件仍然可用?
有没有办法规避这个?毕竟,呼叫已经是同步的,并冻结其他所有内容,直到结果到来。
感谢。
更新:我已经创建了一个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
});
}
答案 0 :(得分:5)
可能解决此问题的方法是在XHR请求返回之前以及您仍在可信上下文中时打开新选项卡。通过Javascript打开的浏览器选项卡和窗口保持与父窗口的连接,并且可以来回通信。
如果在单击链接时打开新选项卡,则可以在XHR调用运行时在新窗口中显示加载屏幕。这个工作流程不像原始请求那么干净,但是如果有一些想法,这将是一个可行的解决方案。下面的脚本只是一个使用window.setTimeout()模拟异步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\'s your data');
}, 5000)
});
});
}(jQuery));
</script>
</body>
答案 1 :(得分:0)
Hello @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);
});
});
通过这种方式,您不需要调用同步请求来在您的上下文中使用该事件,并且作为异步请求,chrome不会抱怨。 :)
答案 2 :(得分:0)
问题不在于XMLHttpRequest
,而在于delay
(同步延迟,可能是WebKit / Blink中的错误)
请参阅示例(代码段中的http://jsfiddle.net/23JNw/32/沙箱不允许弹出窗口):
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 sync)过时对用户体验非常不利。
我尝试过模拟点击,但不能正常工作:
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);
注意:今天的网络浏览器非常聪明,我们很难欺骗它们。
不要使用弹出窗口(我讨厌弹出窗口:)),尝试使用<iframe>
模拟“弹出窗口”:http://demos.jquerymobile.com/1.4.0/popup-iframe/
或使用模态(如引导程序)添加um按钮,并发出询问用户点击的消息:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<link href="//maxcdn.bootstrapcdn.com/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">×</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.com");
});