Skip to content

Observer vs Scroll based lazy loading

Updated: at 09:12 AM

Header Image

This article came out of my desire to find the best lazy loading approach for a good user experience on Eikona (my image hosting platform). In my last article, I talked about how I implemented Websocket streaming for a large number of images. Towards the end of the article, I mentioned that I chose a scroll calculation based method over the popular observer-based lazy loading pattern.

Observer Lazy Loading Pattern

The basic premise with this lazy loading pattern is that there is an invisible DOM element that the user’s scrolling region intersects with, which triggers an event. Usually, when the event is triggered, an HTTP call or Websocket request is made and the resulting data is displayed to the user. Observers are also frequently used to show or hide different web elements on a page as a user scrolls. Below is a great resource for more information about how DOM Observers work.

Scroll Calculation Method

The scroll calculation method is simply a window event listener, window.onscroll and a callback. As the user is scrolling through the page, the window.onscroll method is triggered. This gives you the ability to set a callback that runs whenever the onscroll event is triggered. Within this callback you calculate the height of the document, and compare it to the distance that the user has scrolled, in order to determine where they’re at in relation to the total height of the web page.

The Two Methods Visually Compared

In this comparison, the back-end services function exactly the same. The only difference is in the front-end Vue.js code that makes the data requests.

The green box is the UI Observer element so that it’s clear which one you’re observing 😉.

In first example (the Observer) you’ll notice that there’s a noticable lag between when you reach the amount of images left to scroll, and when the images are actually returned by the services. This creates a slight jarring effect, as the user tries to continue scrolling for more images without there being more images to scroll.

In the second example (scroll method) you can see that on the right side, in the console, as the fetching thumbnails is called, there isn’t any noticeable jarring as data is requested and returned to the UI. The scroll speed in both examples was roughly the same.

In the next example, I’m emulating a user scrolling rapidly, and you can see that the issues with the Observer pattern are further exacerbated. The Scroll method is a bit jarring for the first two calls to the back-end, but becomes as smooth as the slow scroll example after those requests (due to Mediums GIF size limit, I wasn’t able to show those next few events).

I’m able to tweak the Scroll Method a bit more to make the experience even smoother for rapid scrolling, but I chose to try and compare apples to apples for both patterns. In fact, if I were to increase the amount of images loaded to 200 instead of 175, the Scroll Method would outperform the Observer lazy loading pattern by even more than what’s currently displayed for both slow and fast scrolling.

In this case, the Scroll Calculation method outperformed the Observer pattern for lazy loading thousands of images.