Javascript 如何仅在加载URL后调用revokeObjectURL?

Javascript 如何仅在加载URL后调用revokeObjectURL?,javascript,google-chrome,pdf,onload,revokeobjecturl,Javascript,Google Chrome,Pdf,Onload,Revokeobjecturl,我有一个web应用程序。它在谷歌浏览器中运行,不需要在任何其他浏览器中运行 我有在服务器上生成的PDF数据,并在AJAX请求中发送回客户端。 我从PDF数据创建了一个blob。 我使用window.URL.createObjectURL从blob创建URL,然后将其加载到以前创建的用于显示PDF的窗口(我的预览窗口)中 要加载URL,我设置了preview_window.location.href 我想调用revokeObjectURL以避免在窗口中生成和预览新PDF时浪费越来越多的资源。 问题

我有一个web应用程序。它在谷歌浏览器中运行,不需要在任何其他浏览器中运行

我有在服务器上生成的PDF数据,并在AJAX请求中发送回客户端。 我从PDF数据创建了一个blob。 我使用window.URL.createObjectURL从blob创建URL,然后将其加载到以前创建的用于显示PDF的窗口(我的预览窗口)中

要加载URL,我设置了preview_window.location.href

我想调用revokeObjectURL以避免在窗口中生成和预览新PDF时浪费越来越多的资源。 问题在于,在设置preview_window.location.href后立即调用它太早,会阻止显示PDF。因此,我只想在加载URL后调用revokeObjectURL。 为此,我尝试将preview_window.onload设置为回调,但从未调用它

我想知道:

  • 当窗口加载了URL时,是否可以像我尝试的那样触发回调?怎么做
  • 是否有其他方法确保及时调用revokeObjectURL
  • 如果我无法在窗口加载完URL后触发revokeObjectURL,我可能会在生成新URL之前立即撤销每个URL。但如果可能的话,我宁愿在加载完成后立即撤销URL

    我准备了一个html文件,它很好地演示了这种情况:

    <html>
        <head>
            <title>Show PDF Demo</title>
            <script>
                var build_blob = function(mime_type, data) {
                    var buf = new ArrayBuffer(data.length);
                    var ia = new Uint8Array(buf);
                    for (var i = 0; i < data.length; i++) ia[i] = data.charCodeAt(i);
                    var blob = new Blob([ buf ], { type: mime_type });
                    return blob;
                };
    
                window.onload = function(e) {
                    document.getElementById('preview_button').onclick = function(e) {
    
                        // open the window in the onclick handler so we don't trigger popup blocking
                        var preview_window = window.open(null, 'preview_window');
    
                        // use setTimeout to simulate an asynchronous AJAX request
                        setTimeout(function(e) {
                            var pdf_data = atob(
                                "JVBERi0xLjQKMSAwIG9iago8PCAvVHlwZSAvQ2F0YWxvZwovT3V0bGluZXMgMiAwIFIKL1BhZ2Vz" +
                                "IDMgMCBSCj4+CmVuZG9iagoyIDAgb2JqCjw8IC9UeXBlIC9PdXRsaW5lcwovQ291bnQgMAo+Pgpl" +
                                "bmRvYmoKMyAwIG9iago8PCAvVHlwZSAvUGFnZXMKL0tpZHMgWzQgMCBSXQovQ291bnQgMQo+Pgpl" +
                                "bmRvYmoKNCAwIG9iago8PCAvVHlwZSAvUGFnZQovUGFyZW50IDMgMCBSCi9NZWRpYUJveCBbMCAw" +
                                "IDUwMCAyMDBdCi9Db250ZW50cyA1IDAgUgovUmVzb3VyY2VzIDw8IC9Qcm9jU2V0IDYgMCBSCi9G" +
                                "b250IDw8IC9GMSA3IDAgUiA+Pgo+Pgo+PgplbmRvYmoKNSAwIG9iago8PCAvTGVuZ3RoIDczID4+" +
                                "CnN0cmVhbQpCVAovRjEgMjQgVGYKMTAwIDEwMCBUZAooU01BTEwgVEVTVCBQREYgRklMRSkgVGoK" +
                                "RVQKZW5kc3RyZWFtCmVuZG9iago2IDAgb2JqClsvUERGIC9UZXh0XQplbmRvYmoKNyAwIG9iago8" +
                                "PCAvVHlwZSAvRm9udAovU3VidHlwZSAvVHlwZTEKL05hbWUgL0YxCi9CYXNlRm9udCAvSGVsdmV0" +
                                "aWNhCi9FbmNvZGluZyAvTWFjUm9tYW5FbmNvZGluZwo+PgplbmRvYmoKeHJlZgowIDgKMDAwMDAw" +
                                "MDAwMCA2NTUzNSBmCjAwMDAwMDAwMDkgMDAwMDAgbgowMDAwMDAwMDc0IDAwMDAwIG4KMDAwMDAw" +
                                "MDEyMCAwMDAwMCBuCjAwMDAwMDAxNzkgMDAwMDAgbgowMDAwMDAwMzY0IDAwMDAwIG4KMDAwMDAw" +
                                "MDQ2NiAwMDAwMCBuCjAwMDAwMDA0OTYgMDAwMDAgbgp0cmFpbGVyCjw8IC9TaXplIDgKL1Jvb3Qg" +
                                "MSAwIFIKPj4Kc3RhcnR4cmVmCjYyNQolJUVPRg=="
                            );
    
                            /*
                                Warning: for my Chrome (Version 44.0.2403.155 m), the in-built PDF viewer doesn't seem 
                                to work with a blob when this html page is loaded from the local filesystem.  I have only 
                                got this to work when fetching this page via HTTP.
                            */
    
                            var pdf_blob = build_blob('application/pdf', pdf_data);
    
                            var pdf_url = window.URL.createObjectURL(pdf_blob);
    
                            preview_window.onload = function(e) {
                                console.log("preview_window.onload called");  // never happens
                                window.URL.revokeObjectURL(pdf_url);
                            };
    
                            preview_window.location.href = pdf_url;
                            console.log("preview_window.location.href set");
    
                        }, 500);
                    };
                };
            </script>
        </head>
        <body>
            <button id="preview_button">Show Preview</button>
        </body>
    </html>
    
    
    显示PDF演示
    var build\u blob=函数(mime\u类型,数据){
    var buf=新的数组缓冲区(data.length);
    var ia=新的UINT8阵列(buf);
    对于(var i=0;i
    虽然我上面的演示代码避免了它,但我确实为我的应用程序加载了jQuery,所以如果这使事情变得更容易,我愿意使用它


    我确实在搜索中找到了,但在这种情况下,主窗口(“窗口”)指向了一个新的URL,OP在评论中询问窗口是否来自window.open时从未得到响应。

    正如您所发现的,您无法从opener设置
    open()
    ed windows的onload事件。 您必须在第二个页面中插入一些脚本,以调用其
    window.opener
    函数

    但是,由于您正在打开一个pdf文件,浏览器将完全重新解析您的页面,插入的代码将消失

    正如您在评论中发现的那样,解决方案是将blob的url注入iframe中,并等待这个iframe的load事件

    以下是如何:

    index.html

        <script>
            // The callback that our pop-up will call when loaded
            function imDone(url){
                window.URL.revokeObjectURL(url);
                }
    
            var build_blob = function(mime_type, data) {
                var buf = new ArrayBuffer(data.length);
                var ia = new Uint8Array(buf);
                for (var i = 0; i < data.length; i++) ia[i] = data.charCodeAt(i);
                var blob = new Blob([ buf ], { type: mime_type });
                return blob;
            };
            var preview_window=null;
            window.onload = function(e) {
                document.getElementById('preview_button').onclick = function(e) {
                  if(preview_window===null || preview_window.closed){
                    // open the window in the onclick handler so we don't trigger popup blocking
                    preview_window = window.open('html2.html', 'preview_window');
                  }
                   // avoid reopening the window since it may cache our last blob
                  else preview_window.focus();
    
                    // use setTimeout to simulate an asynchronous AJAX request
                    setTimeout(function(e) {
                        var pdf_data = /* Your pdf data */
    
                        var pdf_blob = build_blob('application/pdf', pdf_data);
    
                        var pdf_url = window.URL.createObjectURL(pdf_blob);
                        // Simple loop if our target document is not ready yet
                        var loopLoad = function(url){
                          var doc = preview_window.document;
                          if(doc){
                            var iframe = doc.querySelector('iframe');
                            if(iframe)iframe.src = url;
                            else setTimeout(function(){loopLoad(url);},200);
                          }
                          else setTimeout(function(){loopLoad(url);},200)
                        };
                        loopLoad(pdf_url);
    
                    }, 0);
                };
            };
        </script>
    
    <html>
        <head>
            <title>Iframe PDF Demo</title>
            <style>
                body, html, iframe{margin:0; border:0}
            </style>
        </head>
        <body>
        <iframe width="100%" height="100%"></iframe>
        <script>
            document.querySelector('iframe').onload = function(){
                //first check that our src is set
                if(this.src.indexOf('blob')===0)
                    // then call index.html's callback
                    window.opener.imDone(this.src);
                }
        </script>
        </body>
    </html>
    
    
    //加载时弹出窗口将调用的回调
    函数imDone(url){
    window.URL.revokeObjectURL(URL