簡體   English   中英

JavaScript window.open 有時會返回 null

[英]JavaScript window.open returns null sometimes

我正在嘗試維護一個我沒有編寫的系統(我們不是所有人嗎?)。 它是用 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 開發工具中逐步執行代碼。 這是非常偶然的,並且似乎失敗(返回空值,不打開窗口,無論是否已經存在)多次成功。

我讀了@Joshua 的評論,說創建是異步完成的,所以我認為每次我一步都強制代碼“停止”可能會以某種方式把事情搞砸(盡管在像var w = window.open(...)這似乎不可能發生)。

所以,我拿出了我的斷點......一切都開始完美運行!

我還注意到https://developer.mozilla.org/en-US/docs/Web/API/Window/open ,他們指定如果您重新使用窗口變量和名稱( 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% 有效。

[編輯] 我發現 Stackoverflow 上的代碼片段具有某種防止window.open的安全功能,但此 jsfiddle 顯示了上面的代碼工作,並進行了調整以顯示遞增計數器以證明內容更新按預期工作. https://jsfiddle.net/neekfenwick/h8em5kn6/3/

有點晚了,但我認為這是由於窗口實際上沒有在 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();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM