简体   繁体   English

JavaScript window.open 有时会返回 null

[英]JavaScript window.open returns null sometimes

I am attempting maintenance on a system I did not write (and aren't we all?).我正在尝试维护一个我没有编写的系统(我们不是所有人吗?)。 It is written in C Sharp and JavaScript, with Telerik reports.它是用 C Sharp 和 JavaScript 编写的,有 Telerik 报告。

It has the following code included in JavaScript that runs when the user clicks a button to display a report in a separate window:它在 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
            }

Then the load function:然后加载函数:

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;
}

When I execute this (in Chrome, at least), it does pop up the window and put the report in it.当我执行此操作时(至少在 Chrome 中),它会弹出窗口并将报告放入其中。 However, breakpoints in the c# code indicate that it is getting called 2 or 3 times.但是,c# 代码中的断点表明它被调用了 2 或 3 次。 Breakpoints in the JavaScript and examination of the little log in the JavaScript debugging environment in Chrome show that the call to win.focus() fails once or twice before succeeding. JavaScript 中的断点和 Chrome 中 JavaScript 调试环境中的小日志的检查表明,对win.focus()的调用在成功之前失败了一两次。 It returns an undefined value, and then it appears that the first routine above is executed again.它返回一个未定义的值,然后似乎再次执行了上面的第一个例程。

I am inclined to think it some kind of timing issue, except that the window.open() call is supposed to be synchronous as far as I can tell, and I don't know why it would succeed sometimes and not others.我倾向于认为这是某种时间问题,除了 window.open() 调用应该是同步的,我不知道为什么它有时会成功而不是其他人。 There is a routine that gets executed on load of the window, perhaps that's somehow screwing up the return of the value from open().有一个例程在窗口加载时执行,也许这在某种程度上搞砸了从 open() 返回的值。

I am not a JavaScript person much, as those of you that are can likely tell by this time.我不是一个 JavaScript 人,正如你们中的那些人现在可能已经知道的那样。 If there is something with the code I've put here that you can tell me is incorrect, that's great;如果我放在这里的代码有什么地方你可以告诉我是不正确的,那就太好了; what I'm more hopeful for is someone who can explain how the popup-report-in-frame is supposed to work.我更希望有人能够解释框架内弹出式报告应该如何工作。 Hopefully I can do it without having to replace too much of the code I've got, as it is brittle and was not, shall we say, written with refactoring in mind.希望我可以做到这一点,而不必替换我拥有的太多代码,因为它很脆弱,我们应该说,在编写时并没有考虑到重构。

From what I could find the window.open will return null when it fails to open.据我所知,window.open 在打开失败时将返回 null。 Something may be keeping the browser from opening additional windows a couple of times;某些原因可能会阻止浏览器多次打开其他窗口; maybe it is a popup blocker.也许它是一个弹出窗口阻止程序。

The actual loading of the url and creation of the window are done asynchronously. url 的实际加载和窗口的创建是异步完成的。

https://developer.mozilla.org/en-US/docs/Web/API/Window.openhttps://developer.mozilla.org/en-US/docs/Web/API/Window.open

Popup blocking弹出窗口阻止

In the past, evil sites abused popups a lot.过去,邪恶网站经常滥用弹出窗口。 A bad page could open tons of popup windows with ads.一个糟糕的页面可能会打开大量带有广告的弹出窗口。 So now most browsers try to block popups and protect the user.所以现在大多数浏览器都试图阻止弹出窗口并保护用户。

Most browsers block popups if they are called outside of user-triggered event handlers like onclick.如果在用户触发的事件处理程序(如 onclick)之外调用,大多数浏览器会阻止弹出窗口。

For example:例如:

 // popup blocked window.open('https://javascript.info'); // popup allowed button.onclick = () => { window.open('https://javascript.info'); };

Source: https://javascript.info/popup-windows来源: https : //javascript.info/popup-windows

I just ran into this and it seems to be because I had a breakpoint on the line that calls window.open and was stepping through the code, in Chrome dev tools.我刚刚遇到了这个问题,这似乎是因为我在调用window.open的行上有一个断点,并且正在 Chrome 开发工具中逐步执行代码。 This was extremely hit-and-miss and seemed to fail (return null, not open a window, whether one already existed or not) more times that it succeeded.这是非常偶然的,并且似乎失败(返回空值,不打开窗口,无论是否已经存在)多次成功。

I read @Joshua's comment that the creation is done asynchronously, so I figured that forcing the code to 'stop' each time I step might be screwing things up somehow (though on a single line like var w = window.open(...) doesn't seem like this could happen).我读了@Joshua 的评论,说创建是异步完成的,所以我认为每次我一步都强制代码“停止”可能会以某种方式把事情搞砸(尽管在像var w = window.open(...)这似乎不可能发生)。

So, I took out my breakpoint.. and everything started working perfectly!所以,我拿出了我的断点......一切都开始完美运行!

I also took note of https://developer.mozilla.org/en-US/docs/Web/API/Window/open where they specify that if you are re-using a window variable and name (the second argumen to window.open ) then a certain pattern of code is recommended.我还注意到https://developer.mozilla.org/en-US/docs/Web/API/Window/open ,他们指定如果您重新使用窗口变量和名称( window.open的第二个window.open )然后推荐某种代码模式。 In my case, I am wanting to write HTML content to it, rather than give it a URL and let it async load the content over the network, and I may call the whole function repeatedly without regard for the user closing the window that pops up.在我的情况下,我想向它写入 HTML 内容,而不是给它一个 URL 并让它通过网络异步加载内容,并且我可能会重复调用整个函数而不考虑用户关闭弹出的窗口. So now I have something like this:所以现在我有这样的事情:

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;
    }
}

I'm not convinced the write call should be given the full <html> header but this seems to work 100% for me.我不相信应该给write调用提供完整的<html>标头,但这对我来说似乎 100% 有效。

[edit] I found that a Code Snippet on Stackoverflow has a some kind of security feature that prevents window.open , but this jsfiddle shows the code above working, with a tweak to show an incrementing counter to prove the content update is working as intended. [编辑] 我发现 Stackoverflow 上的代码片段具有某种防止window.open的安全功能,但此 jsfiddle 显示了上面的代码工作,并进行了调整以显示递增计数器以证明内容更新按预期工作. https://jsfiddle.net/neekfenwick/h8em5kn6/3/ https://jsfiddle.net/neekfenwick/h8em5kn6/3/

A bilt late but I think it's due to the window not beeing actually closed in js or maybe the memory pointer not being dereferenced.有点晚了,但我认为这是由于窗口实际上没有在 js 中关闭,或者可能是内存指针没有被取消引用。 I was having the same problem and I solved it by enclosing the call in a try finally block.我遇到了同样的问题,我通过将调用包含在 try finally 块中来解决它。

   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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM