I solemnly promise to be lazy

Yevgeniy Ivanov
3 min readApr 1, 2021

It wasn’t until my first stint with asynchronous javascript that I realized just how much optimization and thought can go into the design and layout of the resource loading of a good web-page.

Javascript is a single-threaded language. This means that as any deed done well, and every man when shopping, all resources are on a single task. When that task is complete, attention and resources move onto the next task in the queue.

This creates an obvious problem, however. What if, say, I want to fetch a resource from an external source. Or maybe even load a few high-resolution images on the site. Now, if you’re in South Korea, where the average download speed is 121 megabit/second, it’s no big deal. But for those of us who have to pace around the house for that one extra bar, it can be very offputting to wait while all the resources are loaded in the order of their appearance. This could mean that a resource at the bottom of the page could take seconds to load. And if there’s one thing that is not a staple of our modern age, it’s patience. So, how is one to about prioritizing what loads and when? In javascript, the answer is asynchronous actions and lazy loading.

My project for the week is a one-page workout and nutrition app that has to make use of external API. This means, request upon request upon request. Now without the asynchronous promise feature of the javascript language, each and every request would have to complete before anything else can happen. So, goodbye images and info until the Paul Revere of our program runs there and back(for every single request).

this.getItemsFromDay(day)    .then(items => this.createDayInstances(items.foods))    .then(daysFoods => this.appendItemsFromDay(daysFoods))    .then(lastItem => lastItem.displayInfo())    .catch(err => {        nutritionMessage.classList.remove('hidden');        nutritionMessage.innerText = err.message;});

The promises feature is great. Not only is it completely obvious what is being done each step, but there is also the amazing “catch” clause which can be triggered anywhere along the way. You can have one promise or a thousand, but only one catch clause is necessary to safeguard the code.

Now, despite javascript being single-threaded, the APIs take care of all the background work while javascript does its thing working with a single stack and heap. And when the requests are finished, the stack is filled and resource displayed when needed.

Another popular way of mitigating a potential block is lazy loading. The idea is to only load a resource when it is needed. This very article, for example, is filled with a few images and gifs. Would it really make sense to load them all as soon as your eyes meet the page? Well, the attention span of the average person is going down with every new meme, so good luck vying for the attention of the audience when there are cute talking huskies on youtube. So, why not load that resource-consuming image when a user stumbles upon it?

let observer = new IntersectionObserver(Food.loadInitialContent.bind(Food));observer.observe(nutritionSection);

An API such as the IntersectionObserver is prime for the job. Only show the user the section when they’re ready to see it. There’s a very neat-looking pattern that I see implemented fairly often of loading a miniaturized and blurred version of an image at the beginning of a page load and then replacing that image with the high-resolution counterpart when its time has come. This removed the somewhat jarring effect of a resource popping out of nowhere when scrolling down the page, and the transition between the blur and high res looks pretty neat as well. Who said being lazy isn’t good?

--

--