Current section: Dynamic Promises 29 exercises
solution

Promise Cache

Loading solution

Transcript

00:00 We've got three loads of the ship every time we load a ship. That is not cool. The way that this is working is we've got these ship buttons right here. Whenever one of those has changed, we set the ship name that changes the state which was initialized to dreadnought, and that ship name is then passed down to our ship details,

00:18 which is wrapped around our error and suspense boundaries. If we dive into ship details, we'll see it's using that ship name to use get ship, to use the promise that's returned from get ship. This is the utility function that we need to memoize,

00:35 I guess, to cache for the promise. Let's come in here and we're going to call this get ship impl. The specific implementation here is not all that important for what we're doing. It's just the implementation and here is the input that is dynamic across different renders and stuff. We're going to do that,

00:54 remove the export because we're not going to export that anymore. Instead, we're going to export a function called get ship. That get ship is going to take the name, which will be a string, and also, sure, we'll want to do the delay so that we can forward it along to the ship impl.

01:12 Then we're going to check the ship cache. Let's make our ship cache first. Ship cache is a new map where the string here, it will be the ship name and the promise resolves to a ship. Then we are going to make our ship promise.

01:30 Promise is equal to the ship cache or calling get ship impl with the name and the delay. If it doesn't exist in the cache already, then we'll trigger the fetch request and get the promise from that. Then we'll update the ship cache to set

01:47 the name property to be assigned to the ship promise, and then return the ship promise. Now, I know somebody is going to ask, so I've got to add it in here. Some of you are going to be like, hey Kent, if it's already in the ship cache, then setting it in the ship cache again, isn't that suboptimal? Yeah, probably yes, but I would be

02:07 surprised if that ever becomes a bottleneck of any application ever. You could refactor this a little bit to say, hey, check the cache first and if it's in there, then don't bother setting it in the ship cache again or whatever. I don't know, maybe that would be slower. You should profile it and then tell me. But this works really well.

02:25 Now with that, would you look at that? Only one call of getShip, and we're not going to get this warning. Hold on, what is this? I know what's going on. I actually have async on here, so getShip is returning a promise, and so we're creating that promise every time.

02:42 We may not be calling the fetch request every single time, but we are definitely creating a new promise and it resolves instantly. Get rid of the async on there. There we go. So now we're not getting the warning and we're not calling getShip every single time or three times when we load

03:00 the page or when we choose between these different ships. You might also notice that now we're not calling it anymore because we still have a promise for each one of these. So that is interesting. As we increment and stuff, we're not going to see the loading states. So this is where we get into caching questions like,

03:17 so what if this data is out of date now? How do we update that and things? That again is outside of the scope of this workshop. That would be a whole other workshop by itself. So we're good with just saying we're going to cache it forever as long as the user is on the page.

03:34 But yeah, you definitely want to think about that in a real application. How do we manage the cache and validation of this stuff? Again, we're doing lower level framework level stuff, typically in a real application you're going to be using a framework that will do lots of this stuff for you already. But it's good and important for you to

03:53 understand how it works under the hood. So there you go. This is caching our promise so that we aren't triggering a fetch call every single render, but instead we just hang on to the previous promise that was generated when the component was initially rendered. Good job.