JavaScript window.open有时返回null
本文关键字:返回 null window open JavaScript | 更新日期: 2023-09-27 17:58:01
我正在尝试维护一个我没有写的系统(不是吗?)。它是用C Sharp和JavaScript编写的,Telerik报道。
当用户单击按钮在单独的窗口中显示报告时,JavaScript中包含以下代码:
var oIframe = $("iframe id='idReportFrame' style='display:none' name='idReportFrame' src=''>");
oIframe.load(function() { parent.ViewReports(); });
oIframe.appendTo('body');
try
{
$('#idReportForm').attr('target', 'idReportFrame');
$('#idReportForm').submit();
}
catch (err) { // I did NOT write this
}
然后加载功能:
function ViewReports()
{
var rptName = $("#ReportNameField").val();
if (rptName == '') { return false; }
var winOption = "fullscreen=no,height=" + $(window).height() + "left=0,directories=yes,titlebar=yes,toolbar=yes,location=yes,status=no,menubar=yes,scrollbars=no,resizable=no, top=0, width=" + $(window).width();
var win = window.open('@Url.Action("ReportView", "MyController")?pReportName=' + rptNameCode, 'Report', winOption);
win.focus();
return false;
}
当我执行这个(至少在Chrome中)时,它确实会弹出窗口并将报告放入其中。然而,c#代码中的断点表明它被调用了2或3次。JavaScript中的断点和Chrome中JavaScript调试环境中的小日志检查表明,对win.focus()
的调用在成功之前会失败一两次。它返回一个未定义的值,然后看起来上面的第一个例程再次执行。
我倾向于认为这是某种时间问题,只是window.open()调用在我看来应该是同步的,我不知道为什么它有时会成功,而在其他情况下不会成功。有一个例程在加载窗口时执行,也许这在某种程度上破坏了open()的值返回。
我不是一个很喜欢JavaScript的人,你们中的那些人很可能在这个时候就知道了。如果我放在这里的代码有什么不正确的地方,你可以告诉我,那太好了;我更希望的是有人能解释框架中的弹出报告应该如何工作。希望我能做到这一点,而不必替换太多我现有的代码,因为它很脆弱,而且我们可以说,它不是在考虑重构的情况下编写的。
据我所知,当window.open无法打开时,它将返回null。某些东西可能会阻止浏览器打开额外的窗口几次;也许它是一个弹出窗口拦截器。
url的实际加载和窗口的创建是异步完成的。
https://developer.mozilla.org/en-US/docs/Web/API/Window.open
弹出式阻止
在过去,邪恶的网站经常滥用弹出窗口。坏页面可能打开大量带有广告的弹出窗口。所以现在大多数浏览器都试图阻止弹出窗口并保护用户。
如果弹出窗口在外部调用,大多数浏览器都会阻止弹出窗口用户触发的事件处理程序,如onclick。
例如:
// popup blocked window.open('https://javascript.info'); // popup allowed button.onclick = () => { window.open('https://javascript.info'); };
来源:https://javascript.info/popup-windows
我刚刚遇到这个问题,这似乎是因为我在调用window.open
的行上有一个断点,并且正在Chrome开发工具中遍历代码。这是一次非常偶然的尝试,而且似乎失败了多次(返回null,不打开窗口,无论窗口是否已经存在)。
我读到@Joshua的评论,说创建是异步完成的,所以我认为每次我踩代码时强制"停止"可能会以某种方式把事情搞砸(尽管在像var w = window.open(...)
这样的单行上似乎不可能发生这种情况)。
所以,我去掉了断点。。一切都开始完美运转!
我还注意到https://developer.mozilla.org/en-US/docs/Web/API/Window/open其中它们指定,如果您正在重新使用窗口变量和名称(window.open
的第二个自变量),则建议使用特定的代码模式。在我的情况下,我想给它写HTML内容,而不是给它一个URL,让它通过网络异步加载内容,我可能会重复调用整个函数,而不考虑用户关闭弹出的窗口。所以现在我有这样的东西:
var win; // initialises to undefined
function openWindow() {
var head = '<html><head>...blahblah..</head>';
var content = '<h1>Amazing content<h1><p>Isn''t it, though?</p>';
var footer = '</body></html>';
if (!win || win.closed) {
// window either never opened, or was open and has been closed.
win = window.open('about:blank', 'MyWindowName', 'width=100,height=100');
win.document.write(head + content + footer);
} else {
// window still exists from last time and has not been closed.
win.document.body.innerHTML = content;
}
}
我不相信write
调用应该得到完整的<html>
头,但这似乎对我来说100%有效
[edit]我发现Stackoverflow上的代码段具有某种安全功能,可以防止window.open
,但这个jsfiddle显示了上面的代码正在工作,并对其进行了调整,显示了一个递增计数器,以证明内容更新按预期工作。https://jsfiddle.net/neekfenwick/h8em5kn6/3/
延迟了一个bilt,但我认为这是由于js中的窗口没有真正关闭,或者内存指针没有被取消引用。我遇到了同样的问题,我通过将调用封装在tryfinally块中解决了这个问题。
try {
if (!winRef || winRef.closed) {
winRef = window.open('', '', 'left=0,top=0,width=300,height=400,toolbar=0,scrollbars=0,status=0,dir=ltr');
} else {
winRef.focus();
}
winRef.document.open();
winRef.document.write(`
<html>
<head>
<link rel="stylesheet" href="/lib/bootstrap/dist/css/bootstrap.min.css">
</head>
<body>
${$(id).remove('.print-exclude').html()}
</body>
</html>
`);
winRef.document.close();
winRef.focus();
winRef.print();
} catch { }
finally {
if (winRef && !winRef.closed) winRef.close();
}
您必须指定新窗口的宽度和高度。所以
window.open("https://avangsoft.ir/", "MyWindowName","width=100,height=100");
有效,但
window.open("https://avangsoft.ir/", "MyWindowName");
不工作