1import { awaitImageLoad, IS_MOBILE, spinningImageDiv } from './utils.js'; 2 3class LazyImageLoaderQueue { 4 constructor() { 5 this.queue = []; 6 this.loadingCount = 0; 7 this.maxConcurrentLoads = IS_MOBILE ? 4 : 8; 8 } 9 10 lock = Promise.resolve(); 11 12 // Function to load an image 13 async loadImage(queueItem) { 14 const { imgElement, callback, onError } = queueItem; 15 try { 16 imgElement.src = imgElement.getAttribute('lazy-src'); 17 await awaitImageLoad(imgElement); 18 callback(imgElement); 19 } catch (err) { 20 onError(err); 21 } 22 await this.lock; 23 this.lock = new Promise((resolve) => { 24 this.loadingCount -= 1; 25 resolve(); 26 this.loadNextImage(); 27 }); 28 } 29 30 // Add image to the queue and try to load 31 queueImage(imgElement) { 32 return new Promise((resolve, reject) => { 33 this.queue.push({ imgElement, callback: resolve, onError: reject }); 34 this.loadNextImage(); 35 }); 36 } 37 38 // Load the next image if the loading count is less than max 39 loadNextImage() { 40 if (this.loadingCount < this.maxConcurrentLoads && this.queue.length > 0) { 41 this.loadingCount += 1; 42 const queueItem = this.queue.shift(); 43 this.loadImage(queueItem); 44 } 45 } 46} 47 48export const lazyImageLoaderQueue = new LazyImageLoaderQueue(); 49 50export function createLazySpinningImage(src, alt, className = '') { 51 const lazyImage = spinningImageDiv({ 52 loading: 'eager', 53 alt, 54 'aria-label': alt, 55 'lazy-src': src, 56 class: className, 57 }); 58 59 const promise = new Promise((resolve, reject) => { 60 const imgInterSectionObserver = new IntersectionObserver((entries) => { 61 const entry = entries[0]; 62 const { target } = entry; 63 const imgEl = target.querySelector('img'); 64 if (entry.intersectionRatio > 0) { 65 lazyImageLoaderQueue.queueImage(imgEl).then(() => { 66 target.classList.add('loaded'); 67 resolve(); 68 }).catch(reject); 69 } 70 }); 71 imgInterSectionObserver.observe(lazyImage); 72 }); 73 74 return { lazyImage, promise }; 75}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.