簡體   English   中英

加載圖像后撤消ObjectURL

[英]revokeObjectURL after loading images

我使用revokeObjectURL來防止 memory 泄漏。

這是我的問題的示例代碼。

 function App(){ const [urls, setUrls] = React.useState([]); const handleUpload = (e) => { const file = e.target.files[0]; const blobUrl = window.URL.createObjectURL(file); setUrls((prev) => prev.concat(blobUrl)); }; return ( <div className="App"> <input type="file" onChange={handleUpload} /> <div> {urls.map((url) => ( <p key={url}> <a href={url} target="_blank"> {url} <img src={url} width={25} /> </a> <button onClick={() => window.URL.revokeObjectURL(url)}> Revoke </button> </p> ))} </div> </div> ); } ReactDOM.render( <App />, document.getElementById('root') )
 <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <div id="root"></div>

當我上傳圖像時,我可以使用createObjectURL()創建圖像文件到 blob url

我擔心 memory 泄漏,所以我為revokeObjectURL()制作了一個按鈕。

單擊撤銷按鈕后,我預計圖像不再顯示。

如果我加載圖像並在撤銷 url 之后,它是否仍然解決了 memory 泄漏?

我想知道,因為圖像仍在顯示。

您必須了解createObjectURL(blob)將返回一個新的 URL 指向瀏覽器的 memory 中的某個位置,在該位置可以訪問 Blob 以便被各種 API 獲取。

調用revokeObjectURL()將斷開此鏈接,因此在此調用后導航、獲取、加載此 URL 將全部失敗。

這通常是重要的 memory 明智的,因為只要這個鏈接是“活動的”,瀏覽器不知道它是否可以釋放它在 memory 中擁有的 Blob 數據的鏈接。 返回的 URL 只是一個字符串,它不知道你用它做了什么,而且與我們在 JS 中的其他指針不同,它的垃圾收集器無法知道是否還有東西會使用它。
通過調用revokeObjectURL() ,您可以讓垃圾收集器知道 Blob 不再鏈接到該 URL 並且如果沒有其他東西持有指向它的指針,它可以收集它。

但是,已經使用此 URL 的 API 現在可以訪問 Blob 的另一個 object。 例如, <img>元素不會不斷地獲取 URL 來獲取另一端的資源。 如果這樣做,網絡流量將是巨大的。 相反,它獲取一次,將結果存儲在 memory 中,然后保留它。 (請注意,對於 blob:URL,結果可能不應該存儲在緩存中,盡管這里存在互操作問題,Firefox 確實以某種方式緩存它,Chrome 沒有)。

 const img = document.querySelector("img"); document.createElement("canvas").toBlob(blob => { const url = URL.createObjectURL(blob); img.src = url; img.onload = (evt) => { img.onload = null URL.revokeObjectURL(url); img.src = ""; setTimeout(() => img.src = url); const img2 = new Image(); img2.src = url; document.body.append(img2); } })
 img { border: 1px solid; }
 <img>

在 Chrome 中,上面的代碼片段會產生兩個損壞的<img> ,而在 Firefox 中它將產生兩個 300x150px 的透明圖像,而在 Safari 中,它將產生一個 300x150px 和一個損壞的圖像)。

我還不確定誰是對的,但在這兩種情況下,URL 實際上已正確損壞,正如在鏈接被撤銷后嘗試導航鏈接所看到的那樣。 如果在 Firefox 中我們仍然加載了圖像,那是因為<img>確實使用了可用圖像列表並且他們沒有從那里刪除它。 因此,即使在您撤銷 URL 之后,它們仍然有可用的內部圖像數據。 同樣,如果您對 URL 執行fetch()操作,您將獲得數據的副本,並且即使在 URL 被撤銷后,該副本仍然有效。 如果您確實導航到該 URL (例如通過<iframe> ,加載的文檔仍然存在。但是 URL 和原始 Blob 的數據之間的初始鏈接被破壞了。垃圾收集器可以完成它的工作並刪除 Blob來自 memory。

但我應該注意,由於這里是創建 blob 的特殊情況:從通過<input>標記選擇的文件中的 URI,實際 Blob 的數據不存儲在 memory 中,而是存儲在用戶的磁盤上。 這意味着,在這種情況下,blob: URI 實際上只是指向磁盤上數據的指針,並且撤銷它幾乎沒有用,因為 Blob 的數據不占用任何 memory。

暫無
暫無

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

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