What I Learned at Work this Week: Lazy Loading

Photo by Dương Nhân from Pexels

I write this blog to explicitly prevent situations like one I had at work this past week. While pair programming with a coworker, he posited that an issue we were facing might have to do with lazy loading. The conversation went something like:

Coworker: Hm this could be caused by lazy loading, but I don’t quite remember how it works…do you?

Me: I…don’t know if I ever learned that.

It wasn’t a big deal and my coworker didn’t have any sort of negative reaction to that revelation, but I would have much preferred to be able to contribute to the discussion. And, as it turns out, I probably could have! Lazy loading is a pretty broad term that refers to a variety of methods used to improve the web browsing experience by loading different parts of a website independently. I built apps that utilized lazy loading in boot camp, but I hadn’t used the term. Today, I’ll dig deeper into the definition.

What is the use of lazy loading?

The websites and apps we develop are packed full of data, namely text and images. Some of this data, like html text, will render almost immediately to our page. Images or large collections of data being fetched from an external database will take longer to load, using memory and other precious resources we’d prefer to devote to other tasks. Ideally, we as programmers produce an excellent user experience while minimizing resource requirements, so it’s advantageous to use lazy loading to render text and images only the parts of a screen that our user will see when they start browsing. If they click a link on the top of the page, we’ll never load what’s below. If they scroll down, we’ll trigger the loading of additional data!

Social media sites with timelines are an ideal use case for this functionality. If you’d like to take a look, head over to the site of your choice (I used Twitter) and open the Network tab in developer tools. The first thing that you might notice is that your site makes a lot of network calls, even if there aren’t that many things rendered to the screen. But the load does stop fairly quickly. Once that happens, try scrolling down and you should see additional calls being made.

These are calls to the site’s database to collect additional data and render older posts. The alternative would be to load every possible post when you first log onto the site, which we know is impractical. So sites like Twitter often use an event listener on a user’s scroll or a “load more posts” button.

Implementing Lazy Loading

If you’re like me, you probably realized that you knew about lazy loading all along. We can use JavaScript to conditionally make API calls and render elements on our Document Model Object, as well as add listeners for events like scrolling. Like me, however, you might be thrown off by the fact that a lot of lazy loading explanations don’t mention JavaScript at all. That’s because this framework has been around since before JS was the language of the web and therefore needed implementation methods for classic Object Oriented languages like C#.

These implementation methods often require an alternate object that is either used as a placeholder or used to assign values to the actual object we’re looking to load data for. They are commonly referred to as lazy initialization, virtual proxy, ghost, and value holder.

Lazy Initialization

With lazy initialization, we initialize an object with a null value, but add a condition to the object’s class definition so that a value will be assigned if the get method is invoked. We won’t need to collect all the relevant data until we’re actually asked for it! A lot of the documentation I read mentioned C#, but since I don’t know C#, I’ll write an example with Java using an Image class with a size attribute:

public class Image {

public getSize {
if (this.size == null) {
// Run logic that queries a database and assigns the result as our size attribute, then returns that value. This method might involve an ID so that we would know which DB object we were looking for.
}
return this.size;
}
}

Only once the getSize method has been called do we have to find the actual size of this object. If it is never called, we never have to go through that process.

Virtual Proxy

Lazy initialization creates an object with values set to null, but why bother with initialization at all if we might never reference the object? A virtual proxy is a generic object that can stand in place of our actual object, if it is ever needed. The proxy should have the same interface as the future object so that it will have all the same methods. Once one of those methods are invoked, they will initiate the creation of the actual object. So if we had a cooking app with an IngredientsList interface, we would create a class, IngredientsListImplementation, to use when we wanted to create a list of ingredients. But, until then, we’d use IngredientsListProxy instead:

public class IngredientsListProxy implements IngredientsList {
private IngredientsList ingredientsList;

public List <Ingredient> getIngredients {
if (ingredientsList == null) {
System.out.println(“Fetching list of ingredients”);
ingredientsList = new IngredientsListImplementation();
}
return ingredientsList.getIngredients();
}
}

Our proxy creates a null variable (ingredientsList) that simply possesses the characteristics of the IngredientsList interface. Once we try to reference the attributes of that object (which are currently null), it will trigger the creation of a different object and call the same method on that one, which will have actual values!

Ghost

When using a ghost, we initialize our actual desired object instead of a placeholder or proxy. This object will contain some of the relevant information we’ll ultimately need, but other attributes will be left blank. Generally it will be created with little more than an ID and then populated with data when one of its methods are called. We might have a list of attributes that looks like this:

objectID = uniqid();
objectName = '';
objectImageUrl = '';

Value Holder

A value holder is a generic object whose methods replace the attributes of a specific object. So, rather than assign all values to an object that may not be used when our page loads, we simply create this generic value holder. We can initialize a value holder for each actual object we would be referencing. A value holder method may look like this:

public String getIngredientName {
if (ingredientName == null) {
ingredientName = // a method to query the database
}
return ingredientName;
}

Making lazy loading easy

I personally found these four methods to be challenging because they didn’t have a lot of commonality with the type of code that I write, which more often relies on JavaScript for user interaction. To that end, a lot of the technique for lazy loading has been abstracted from us thanks as always to new frameworks, IDE extensions, and convenient language updates. For example, if we had an HTML image that we didn’t want to load until a user scrolled down to that part of the page:

<img src='img1.jpg'>

We could make that happen by adding a simple attribute to the code:

<img loading='lazy' src='img1.jpg'>

It’s always valuable to better understand how functions work, even when we may never have to code them ourselves. Though lazy loading is only getting more intuitive, the techniques behind it can be useful for solving other problems or refreshing our knowledge of Object Oriented Programming concepts. Check out the resources I used to write this article if you’d like to see more complex lazy loading code, or if you’re looking for more practical advice on how to solve problems commonly caused by lazy loading.

Sources

--

--

--

Solutions Engineer

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Install Kali Linux 2020.4 on Windows — Complete Beginner Guide

11 Golden Rules For Android App Development

Encode Hackathon: The Winners

What is hashing and why hashing is required?

Coding with Feature Flags: How-to Guide and Best Practices

The advantages of agile testing

IF YOUhttps://nytimes.one/if-you-pick-your-nose-you-should-probably-stop-now-this-is-how-dangerous-i

[Algo]: Interwoven Strings

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Mike Diaz

Mike Diaz

Solutions Engineer

More from Medium

Why do not use Math.random()

Solid Design Principles In Javascript (Part 1) — Single Responsibility Principle

4 Ways of Creating an Object in Javascript

Creating an object in Javascript

Why You Should Write Your Javascript codes like a Product? Coding like Product, Best Practises