【问题标题】:JavaScript window.open returns null sometimesJavaScript window.open 有时会返回 null
【发布时间】:2014-04-11 18:02:51
【问题描述】:

我正在尝试维护一个不是我编写的系统(我们不都是吗?)。它是用 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 人,你们中的那些人现在可能已经知道了。如果我放在这里的代码有什么地方你可以告诉我不正确,那就太好了;我更希望的是有人可以解释 popup-report-in-frame 应该如何工作。希望我可以做到这一点,而不必替换我拥有的太多代码,因为它很脆弱,并且我们可以说,在编写时没有考虑到重构。

【问题讨论】:

    标签: c# javascript window.open


    【解决方案1】:

    据我所知,window.open 在打开失败时会返回 null。某些东西可能会阻止浏览器多次打开其他窗口;也许它是一个弹出窗口阻止程序。

    url 的实际加载和窗口的创建是异步完成的。

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

    【讨论】:

    • +1。这对我来说是一个弹出窗口阻止程序! (即使在 Intranet 站点上 - 哦!)。拦截器是 uBlockOrigin(根据我的经验,它很少引起问题)。
    【解决方案2】:

    弹出窗口拦截

    过去,邪恶网站经常滥用弹出窗口。可能会打开一个错误的页面 大量带有广告的弹出窗口。所以现在大多数浏览器都试图阻止 弹出窗口并保护用户。

    如果在外部调用弹出窗口,大多数浏览器都会阻止它们 用户触发的事件处理程序,例如 onclick。

    例如:

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

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

    【讨论】:

      【解决方案3】:

      我刚刚遇到了这个问题,这似乎是因为我在 Chrome 开发工具中调用window.open 的行上有一个断点,并且正在单步执行代码。这是非常失败的,并且似乎失败了更多次(返回 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 调用完整的 &lt;html&gt; 标头,但这似乎对我来说 100% 有效。

      [编辑] 我发现 Stackoverflow 上的代码片段有某种安全功能可以阻止 window.open,但是这个 jsfiddle 显示了上面的代码工作,并通过调整显示递增计数器来证明内容更新是按预期工作。 https://jsfiddle.net/neekfenwick/h8em5kn6/3/

      【讨论】:

        【解决方案4】:

        迟到了,但我认为这是由于窗口实际上没有在 js 中关闭,或者可能是内存指针没有被取消引用。 我遇到了同样的问题,我通过将调用包含在 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();
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-04-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多