parent
881bab10df
commit
f06c6fdcbf
|
@ -6,7 +6,7 @@
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
import { fetchImage } from "./XImgCache";
|
import { fetchImage } from "./XImgCache";
|
||||||
|
|
||||||
const BLOB_CACHE: { [src: string]: string } = {};
|
const BLOB_CACHE: { [src: string]: [number, string] } = {};
|
||||||
const BLANK_IMG =
|
const BLANK_IMG =
|
||||||
"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
||||||
|
|
||||||
|
@ -26,11 +26,13 @@ export default defineComponent({
|
||||||
data: () => {
|
data: () => {
|
||||||
return {
|
return {
|
||||||
dataSrc: BLANK_IMG,
|
dataSrc: BLANK_IMG,
|
||||||
|
isDestroyed: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
src() {
|
src(newSrc, oldSrc) {
|
||||||
|
this.cleanup(oldSrc);
|
||||||
this.loadImage();
|
this.loadImage();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -39,9 +41,15 @@ export default defineComponent({
|
||||||
this.loadImage();
|
this.loadImage();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
beforeDestroy() {
|
||||||
|
this.cleanup(this.src);
|
||||||
|
this.isDestroyed = true;
|
||||||
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
async loadImage() {
|
async loadImage() {
|
||||||
if (!this.src) return;
|
if (!this.src) return;
|
||||||
|
this.isDestroyed = false;
|
||||||
|
|
||||||
// Just set src if not http
|
// Just set src if not http
|
||||||
if (this.src.startsWith("data:") || this.src.startsWith("blob:")) {
|
if (this.src.startsWith("data:") || this.src.startsWith("blob:")) {
|
||||||
|
@ -51,20 +59,35 @@ export default defineComponent({
|
||||||
|
|
||||||
// Fetch image with axios
|
// Fetch image with axios
|
||||||
try {
|
try {
|
||||||
const src = this.src;
|
// Use BLOB from cache assuming it exists
|
||||||
|
const usedCache = (src: string) => {
|
||||||
if (BLOB_CACHE[src]) {
|
if (BLOB_CACHE[src]) {
|
||||||
this.dataSrc = BLOB_CACHE[src];
|
this.dataSrc = BLOB_CACHE[src][1];
|
||||||
|
BLOB_CACHE[src][0]++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newBlob = await fetchImage(src);
|
// Check if the blob cache exists now
|
||||||
if (this.src === src) {
|
// In this case, someone else already created the blob
|
||||||
const blobUrl = URL.createObjectURL(newBlob);
|
// Free up the current blob and use the existing one instead
|
||||||
BLOB_CACHE[src] = this.dataSrc = blobUrl;
|
if (usedCache(src)) {
|
||||||
setTimeout(() => {
|
URL.revokeObjectURL(newBlob);
|
||||||
if (BLOB_CACHE[src] === blobUrl) delete BLOB_CACHE[src];
|
} else {
|
||||||
URL.revokeObjectURL(blobUrl);
|
// Create new blob cache entry
|
||||||
}, 60 * 1000);
|
this.dataSrc = newBlob;
|
||||||
|
BLOB_CACHE[src] = [1, this.dataSrc];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.dataSrc = BLANK_IMG;
|
this.dataSrc = BLANK_IMG;
|
||||||
|
@ -76,6 +99,23 @@ export default defineComponent({
|
||||||
if (this.dataSrc === BLANK_IMG) return;
|
if (this.dataSrc === BLANK_IMG) return;
|
||||||
this.$emit("load", this.dataSrc);
|
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];
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in New Issue