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的人,你们中的那些人很可能在这个时候就知道了。如果我放在这里的代码有什么不正确的地方,你可以告诉我,那太好了;我更希望的是有人能解释框架中的弹出报告应该如何工作。希望我能做到这一点,而不必替换太多我现有的代码,因为它很脆弱,而且我们可以说,它不是在考虑重构的情况下编写的。

JavaScript window.open有时返回null

据我所知,当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");

不工作