Observer vs Scroll Lazy Loading
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. If you missed the last article on Websockets and want to catch up, you can check out the article link below.
Websockets streaming magic. Loading thousands of images in Vue.js.
In my last article, I briefly talked about the importance of inexpensive, scalable, and most importantly…
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.
A Few Functional Uses for Intersection Observer to Know When an Element is in View | CSS-Tricks
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.