Check out a free preview of the full Web Storage APIs course
The "Cache-First Load Practice" Lesson is part of the full, Web Storage APIs course featured in this preview video. Here's what you'd learn in this lesson:
Maximiliano walks through refactoring the current load function into a cache-first load. A student's question regarding if there is an e-tag variant of cache invalidation for IndexedDB is also covered in this segment.
Transcript from the "Cache-First Load Practice" Lesson
[00:00:00]
>> Now the next step is to change the load function. We already have the load function. The load function is fetching the menu from the API and rendering the menu. So we need to change that structure, okay? So it's already async, so we are already there. So what we need is the database.
[00:00:22]
So we're going to call Menu.openDB, and remember this returns a promise, so we await for it. So we open the database. And here, something that we can use our count to see if there is something. Because maybe the database is empty. So if it's empty, I don't need to load it from the IndexedDB.
[00:00:48]
If it's empty, I need to go to a network. Does it make sense? Because nothing is there yet in the database. So how can we check that? Well, we can call db.count. Count will count the amount of objects or values in one data store. What's the data store?
[00:01:06]
Categories, okay, but we need to await for that. Can we await in an if condition? Yeah, we can. These days, we can do these things. So if it's zero, it means the database is empty, okay? DB is empty, so it's empty, I need to go and fetch the data.
[00:01:29]
But instead of, Saving the data in my array, I'm going to save it in a local variable. So I'm going to the network, getting the values. Now, what do I need to do with that data? Save it, right? But, I mean, I can stringify this, but yeah, we're not going to do that again, okay?
[00:01:53]
Or I can just save it in one object, but I don't need that. I can take my data, my data is directly, we can call this categories. And forEach, so I can execute forEach. For each category, I can use a lambda expression here. I'm going to talk to my DB, and I'm going to add, One object in the categories store.
[00:02:25]
And that's the value. I think it's fine, yep. Now, Menu.data is not API.fetchMenu, it's getAll, get me all the categories. Does it make sense? The flow, so using async await and using this wrapper, the code, it's okay, it's clean. You can follow the code. You can follow the flow of thought of what's going on.
[00:02:58]
With the original API, because it's event-based, it's actually difficult to do something like this, really simple to get. So I think it should work. By the way, this code that we have here is using a pattern that we haven't mentioned in this workshop today. It's called cache first.
[00:03:22]
What is cache first? So if I do have categories in my database, I'm serving to the rendering the categories from the cache. But what if the server is changing the menu? And not updating the menu. Does it make sense? So this is known as cache first, and it's a pattern, okay?
[00:03:48]
You can use it or not. Hey, it's a pattern. Just have in mind that with this pattern, once you have saved something in the database, you will use that forever. Maybe you need to add another code that every morning or every time you open the app, you check with the server.
[00:04:08]
You download the menu again and you upgrade your database, okay? I will show you another, a second policy, a second algorithm in a minute. Well, let's see this in action. So back in my Coffee Masters website, if I reload. So if I go to the Console, I have an error.
[00:04:35]
So I think that we have an error with count in line 17. So it's here, I think that the problem is that I didn't return the database. So I should always return the database. So then I will get the database here, okay? So we have that error there.
[00:05:03]
And now, it's working again. How do I know if this is working or not, this is taken from the database or not? First, let's go to application IndexedDB. Now I have my new data store. And if I open, I have my database and my data store inside. I have four objects, okay?
[00:05:25]
And each object has its array of products inside. But again, as a homework, you would have an exercise to actually also take the product out of this object store and you can create another object store in the cm-menu database. Another way to see if this is working because this is cache first is to change the menu.
[00:05:51]
So this is hot coffee, and I can add some exclamation marks. So if I refresh, I'm not seeing the exclamation marks at all. Because they're coming from the database. If I delete the database and refresh, now it's downloading the data again. Make sense? That's cache first, has advantages and disadvantages.
[00:06:23]
So now every time you get into this web app, the data is already there in the database. I don't need to wait for the menu to arrive. Every time we are working with cache, we have advantages and disadvantages. So you need to find the balance there.
>> For invalidation, we were talking about when you open the app or whatever, turn it off, requests kind of the monocron or last modified version of cache invalidation.
[00:06:55]
Is there an e-tag variant version of cache invalidation for-
>> No, first, e-tags.
>> [INAUDIBLE] not literally e-tags.
>> E-tags are kind of deprecated. Who is using e-tags this day? But anyway, the problem that we have is that HTTP as a protocol, okay, it's client-based. So the client needs to start a request.
[00:07:19]
So the problem is that server side, we know when we are changing the menu. So how the server can let the client know that there are changes, that's the challenge. So there are design patterns, okay, to do that. Now you can have a manifest JSON file with metadata with a timestamp.
[00:07:37]
So every time you open your web app, you download that JSON. You check with your local storage timestamp, and you see if there is a new version of the data, and then you start an update process. Or you can use one of the new APIs available. Check my course of Frontend Masters, JavaScript in the background.
[00:07:56]
So you have background sync, periodic background sync. So you can actually ask the browser to every morning check if there is a new menu. And then you update IndexedDB in the background or you can send a push message, and the push message will wake up a service worker.
[00:08:15]
And because service worker has access to IndexedDB, the service worker, even if you're not using the app can go and update the menu. So next time you open the app, the menu is updated.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops