From d86e9406d38238eac08a9eaa995193a148b379bf Mon Sep 17 00:00:00 2001 From: Varun Patil Date: Sat, 25 Feb 2023 21:09:34 -0800 Subject: [PATCH] x-img: simplify logic of cache --- src/components/frame/XImg.vue | 70 ++++++++--------------------------- 1 file changed, 15 insertions(+), 55 deletions(-) diff --git a/src/components/frame/XImg.vue b/src/components/frame/XImg.vue index efe3b0b6..c2790b6a 100644 --- a/src/components/frame/XImg.vue +++ b/src/components/frame/XImg.vue @@ -6,7 +6,7 @@ import { defineComponent } from "vue"; import { fetchImage } from "./XImgCache"; -const BLOB_CACHE: { [src: string]: [number, string] } = {}; +const BLOB_CACHE: { [src: string]: string } = {}; const BLANK_IMG = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"; @@ -26,13 +26,11 @@ export default defineComponent({ data: () => { return { dataSrc: BLANK_IMG, - isDestroyed: false, }; }, watch: { - src(newSrc, oldSrc) { - this.cleanup(oldSrc); + src() { this.loadImage(); }, }, @@ -41,15 +39,9 @@ export default defineComponent({ this.loadImage(); }, - beforeDestroy() { - this.cleanup(this.src); - this.isDestroyed = true; - }, - methods: { async loadImage() { if (!this.src) return; - this.isDestroyed = false; // Just set src if not http if (this.src.startsWith("data:") || this.src.startsWith("blob:")) { @@ -59,35 +51,20 @@ export default defineComponent({ // Fetch image with axios try { - // Use BLOB from cache assuming it exists - const usedCache = (src: string) => { - if (BLOB_CACHE[src]) { - this.dataSrc = BLOB_CACHE[src][1]; - BLOB_CACHE[src][0]++; - return true; - } - return false; - }; + const src = this.src; + if (BLOB_CACHE[src]) { + this.dataSrc = BLOB_CACHE[src]; + return; + } - // Check if the blob cache exists - if (!usedCache(this.src)) { - const src = this.src; - const newBlob = URL.createObjectURL(await fetchImage(src)); - if (this.src !== src || this.isDestroyed) { - URL.revokeObjectURL(newBlob); // the src has changed, abort - return; - } - - // Check if the blob cache exists now - // In this case, someone else already created the blob - // Free up the current blob and use the existing one instead - if (usedCache(src)) { - URL.revokeObjectURL(newBlob); - } else { - // Create new blob cache entry - this.dataSrc = newBlob; - BLOB_CACHE[src] = [1, this.dataSrc]; - } + const newBlob = await fetchImage(src); + if (this.src === src) { + const blobUrl = URL.createObjectURL(newBlob); + BLOB_CACHE[src] = this.dataSrc = blobUrl; + setTimeout(() => { + if (BLOB_CACHE[src] === blobUrl) delete BLOB_CACHE[src]; + URL.revokeObjectURL(blobUrl); + }, 60 * 1000); } } catch (error) { this.dataSrc = BLANK_IMG; @@ -99,23 +76,6 @@ export default defineComponent({ if (this.dataSrc === BLANK_IMG) return; this.$emit("load", this.dataSrc); }, - - async cleanup(src: string) { - if (!src) return; - - // Wait for 1s before collecting garbage - await new Promise((r) => setTimeout(r, 1000)); - - // Clean up blob cache - const cache = BLOB_CACHE[src]; - if (!cache) return; - - // Remove blob from cache - if (--cache[0] <= 0) { - URL.revokeObjectURL(cache[1]); - delete BLOB_CACHE[src]; - } - }, }, });