Why it took so long to do infinite scroll with IntersectionObserver() browser API & image generator function?

Girish Venkatachalam
3 min readJul 4, 2024

--

I guess though I did publish an article on infinite scroll laying bare all the gory details I shall chronicle why I struggled so much.

It is actually simple to do Image generator using yield() to fetch next 20 images from a full list of images that need not be a multiple of 20.

Look a this code.

 function * imageIterator(images, perPage) {
let position = 0;

while (position < images.length) {
yield images.slice(position, position + perPage);
position = position + perPage;
}
}
imageArr = ['img1.jpg', 'img2.jpg', 'img3.jpg', 'img4.jpg'];

iT = imageIterator(imageArr, 20);

do {
next20img = iT.next.value();
for(var i = 0; i < next20img.length; i++) {
img = next20img[i];
const newImg = document.createElement("img");
newImg.src = img;
document.body.append(newImg);
}
}while(!iT.next().done);

So far so good. We have an iterator/generator with * in front of function name.

Then you invoke it to get next batch of 20 images.

You stop iteration once you find the done flag or like I did, when the length of results are less than 20.

In above examples I append to the body tag by constructing image object and setting src attribute.

Okay so you can test this and find that you get a bunch of images from a huge list of images as array. This is useful for a lot of applications.

You may use it for sending it to someone with a REST API or use a marker between these batches or construct a pagination in browser.

There are obvious applications beyond infinite scroll.

Now for infinite scroll you only need this code.

this.observer = new IntersectionObserver(
(entries, self) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
self.unobserve(entry.target);
// observe the next batch
let images = getImages();
self.observe(images[imageCount]);
} else {
requestImages(imagesPerRequest);
}
}
});
}, {
root: document.querySelector('#div2'),
rootMargin: "0px",
threshold: 1
}
);
fuction requestImages(perpage) {
let firstImage = container.lastChild;
observer.observe(firstImage);
console.log("Setting up observer");
}

I faced significant struggle to get this going. Reason being the observer.observe() code was not getting kicked at all.

After wasting significant time comparing with original code from Codepen I identified the bottleneck.

The browser was constantly showing one image. It was frustrating.

Obviously I was new to this API. Moreover I found another sample from stackoverflow() that confirmed my guess.

Moreover the code sample I got was using pixabay REST API to fetch images infinitely.

My use case for Photoveda image editor is using image generator, so I had to refactor.

I got rid of the above while loop and added end condition to stop observing.

            var imageSet = this.iterator.next().value;
if (imageSet.length < this.imagesPerRequest) {
console.log("Time to stop Infinite loading...");
console.log(imageSet.length);
this.stopLoading = true;

for (var i = 0; i < this.imgContent.length; i++) {
this.addImage(this.imgContent[i]);
}
for (var i = 0; i < imageSet.length; i++) {
this.addImage(imageSet[i]);
}
this.observer.unobserve(this.container.lastChild);
return;
}

Coding is fun but only when you have infinitely high pain threshold.

Either way end result is worth it.

Now my OO module for infinite scrolling is done and I can simply use it in any screen of Photoveda where several images are needing to be loaded in a div.

Coding is iterative and needs a mindset of breaking problem down into independent self contained chunks and testing each assumption.

For instance first thing I did was to ensure IntersectionObserver() API was kicking in a div instead of in root window. I needed CSS of overflow:scroll() for this.

Breaking a problem down is the way to achieve progress.

But to write 94 lines of code to make things work my way took a lot of frustration and debugging.

--

--

Girish Venkatachalam

Author of Photoveda image editor Chrome plugin, SDK, API. Vim fanatic. Solopreneur for 19 years. Love coding in Python(Jupyter notebook). Linux fanatic.