تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Problem: Sequential API Calls1:31

So another thing about what we're currently doing is we are making four separate requests to the API for each of the categories here. So one for popular games, one for recently reviewed, one for most anticipated, and one for coming soon. So if you look at our code, if you go to our GamesController, we have one here, here, here, and here. Now because php is not asynchronous, each one of these calls have to wait for the previous one to complete. So each call stacks upon the last call. Now if this were JavaScript, and we were making use of promises, then that wouldn't be an.

So each call stacks upon the last call. Now if this were JavaScript, and we were making use of promises, then that wouldn't be an issue because the app continues to execute until the promise resolves, and then the app is re-rendered. But we are in PHP, so we have to look for an alternate solution. So just to prove to you that that's the case, if I remove the first or the last three calls, and just die and dump the first one, you'll see that it's slightly faster. We lost the timer, but you can feel that it's slightly faster. So let me just put that back. And one solution is that if we can find a way to just make one request to the server,

Multi-Query Alternative (Guzzle)3:45

And then you'll get the keys back corresponding to what you name them here. And all this is done in one request. So I hope that makes sense. So we can actually do this. And we only need one request to the server, or to the API, I mean. So I hope that makes sense. Unfortunately, I couldn't get it working with the HTTP client within Laravel. But I did get it working within Guzzle, which is what the HTTP client uses under the hood. So we're not going to go with this approach, but I'll just paste in the code and comment it out if you want to use this approach.

So we're not going to go with this approach, but I'll just paste in the code and comment it out if you want to use this approach. So let me just paste it in. So here's the code. Like I said, I'm making use of Guzzle here. And here is the endpoint. And we're making a POST request to the multi-query endpoint. I have the key here. And here are our two queries. And I am just dying and dumping the response here.

Livewire Async Approach5:28

And all of the AJAX requests can happen at the same time. So that would be an option. If you ever used Vue before and made AJAX requests, you'd see that they would load on top of when the shell of the app is already loaded. And they would load asynchronously. So they would load at the same time. So we're going to take an approach like that. But instead of using Vue or JavaScript, we're going to be using Livewire. So like I said, it's the same approach. But we're making use of Livewire components, because Livewire is awesome and easy to use.

Setup Livewire Assets5:55

So like I said, it's the same approach. But we're making use of Livewire components, because Livewire is awesome and easy to use. So let's go ahead and compose a required Livewire. Okay. And let's include the assets. So Livewire styles and Livewire scripts. So let's go into our template. So app.blade.php. So let's put the styles in here. And let's put the scripts right here.

So let's put the styles in here. And let's put the scripts right here. Okay. Cool. And let's go ahead and make a component. So let's do php artisan make:livewire. And we need to make a component for everything that makes an AJAX request. So in our case, we need to make four components. One for this popularGames, one for recentlyReviewed, one for mostAnticipated, and one for comingSoon.

Build PopularGames Component6:46

One for this popular games, one for recently reviewed, one for most anticipated, and one for coming soon. So let's start with the popular games. So let's make a component and say PopularGames. Okay. So that made a class and a view. And now we want to extract the logic for popularGames into that component. So let's grab this. So I'm going to grab this. And I'm going to go to popularGames, which is in app/Http/Livewire/PopularGames.php.

So I'm going to grab this. And I'm going to go to popularGames, which is an app/Http/Livewire/popularGames. And I am going to actually let me just render the view first. So I'll leave this in here for now. And let's go to our index.blade.php, which is right here. And I'm just going to grab everything that we need for our popularGames. So it should be this. So I'm going to grab this and cut this out. And I'm going to replace it with a Livewire component. So Livewire popularGames.

And I'm going to replace it with a Livewire component. So Livewire popularGames. Okay. And now if you go into resources/views Livewire popularGames, we can just paste that in here. And that should work. Let's make a change here. All right, it's not going to work yet, because we have to pass in the popularGames. So let's do that. So let's go to popularGames. And I'm going to make a public property for the popularGames.

So let's go to popular games. And I'm going to make a public property for the popularGames. And anything that's a public property gets automatically passed into the view. And we want the popularGames to be passed into the view. So say public $popularGames is an empty array. Okay. So now this should work, but our popularGames would be empty. Okay, but like I said, it's empty. So I'm going to make a new method here. And this is going to be the method responsible for loading our games from the API.

So I'm going to make a new method here. And this is going to be the method responsible for loading our games from the API. So let's call it loadPopularGames. And there's no params. And here is where we can paste or grab the code that gets information from the API and paste it in here. Okay. And we need the before and after variables. So let's grab those. So we can grab these two.

So let's grab those. So we can grab these two. Let's comment this out, since we don't need it anymore. Let's comment this out, since we don't need it anymore. Okay. Let's paste it in here. Okay, cool. And this won't change anything. Undefined variable before. Oh, that's because our controller still needs that variable.

Undefined variable before. Oh, that's because our controller still needs that variable. So we'll leave this in here until we refactor it later. So this is still the same, still going to be empty. Oh, yeah, let's make sure to not pass it in here. We don't need this anymore. So let's comment that out. See if this works. Okay, so it's still empty, but we're not loading our games yet. So if you look at the Livewire documentation, and if you go down here to defer loading,

Okay, so it's still empty, but we're not loading our games yet. So if you look at the Livewire documentation, and if you go down here to defer loading, it says Livewire offers a wire:init directive to run an action as soon as the component is rendered. And that's exactly what we want to do. So there's an example here, which has this Boolean readyToLoad. And then if you look here, this is what we need in our component. When this component is mounted, then run this loadPosts method within the class. So that's what we need in our component. Let's go to our PopularGames component and say wire:init loadPosts.

So that's what we need in our component. Let's go to our PopularGames component and say wire:init loadPopularGames. In our case, it's what I named it loadPopularGames. So now this is going to render, it's going to encounter this Livewire PopularGames, it's going to go in here, it's going to say on initialization loadPopularGames. And here is where we will load our popular games from the API. And then this has to change. So we want to update the public property. So it's gonna be this popularGames. And once this is changed, then this render method will run again and the view will re-render.

So it's gonna be this popular games. And once this is changed, then this render method will run again and the view will re-render. So if I did everything correctly, this should work. And it does, but Carbon is not found. So let's import Carbon. Okay, and let's try again. And HTTP is not found, of course, try again. And this should work. And there you go, you see the popular games load. And as you saw, this came in after the shell of the App loaded, and it was re-rendered.

Okay, let's try again. Okay, there you see the loading indicator there, or the loading text. And if you look down here, you'll see that it loads a bit quicker here. So 463, as opposed to somewhere between two and three. So now if you do the same thing to these other components, then this shell will load quickly. And then these Livewire components will go off and make requests to the API. So let's quickly do that. So let's do this again. Let's make one called RecentlyReviewed. Okay, let's go into our index.

Let's make one called RecentlyReviewed. Okay, let's go into our index. Let's grab this. So everything in this div will be in this new Livewire component. So let me just cut this out. And let me say livewire, recentlyReviewed. Okay, let's go to that component RecentlyReviewed, paste that in. Let's reinvent this. Let's say wire:init as well. So wire:init equals, let's say loadRecentlyReviewed.

Let's say wire:init as well. So wire:init equals, let's say loadRecentlyReviewed. Let's also use a for else in here. And say empty, I just had a div that was loading. And let's end the for else. Okay, let's go into our GamesController and grab everything we need for recentlyReviewed. So everything here, and we need before and current. So we'll grab that as well. So let me put this in recentlyReviewed. And we made a method called loadRecentlyReviewed.

So let me put this in recently reviewed. And we made a method called loadRecentlyReviewed. Okay, and it's pasted this in. And we need before and current. So let me just grab that. Okay, let's put that up here. And we don't need after. And this has to be a instance variable. And let's put it up here. Let's make it public.

And let's put it up here. Let's make it public. Recently reviewed, oops. equals empty to start. Okay. And it's import Carbon and the HTTP client. Okay, let's see if I did everything correctly in one shot. Oh, yeah, let's make sure to remove recently reviewed here. And I think that's it. See if this works.

And I think that's it. See if this works. So popular games, see if it works for recently reviewed games. And it does. Cool. So I'm not gonna make you watch me do it for these two. It's the same process, and I will be back when it's done. Okay. So I've added Livewire components for these two as well. So now everything is within a Livewire component.

So I've added Livewire components for these two as well. So now everything is within a Livewire component. So now if I reload, if you look at the response time here, it's now down to just the time for one response to come back. But if you refresh, the perceived loading time is even quicker because the shell of the app loads instantly while our Livewire components make AJAX requests to the API. And then they re-render once that data comes back. Also an added benefit is our code is much cleaner, separated into components. If you look at our controller, there's actually nothing in here except returning the view. This is just the multi query, which I showed you earlier, which I'll leave commented out.

Add Spinners and Caching17:03

If you look at our controller, there's actually nothing in here except returning the view. This is just the multi query, which I showed you earlier, which I'll leave commented out. Our view is much cleaner because we've put everything into separate Livewire components. So everything is looking quite good. So one more thing I want to add here is instead of just the loading dot dot dot, I want to add a loading spinner. So I'm going to make use of a Tailwind CSS loading spinner library, which I usually use when I need a loading spinner. So let's go ahead and install this. So choose npm and make use of this.

So let's go ahead and install this. So choose NPM and make use of this. So while that's going, let's just install it. So we need to add this spinner key in our theme. So let's go ahead and do that. So let's go to a tailwind.config.js. And let's put it in our theme, put it after extend, space that in. And I'm going to change the size to make it 2em to make it a bit bigger. Actually, I'll just leave it at 1 because we're not going to use the spinner later on. So I'll just leave it to default.

Actually, I'll just leave it at one because we're not going to use the spinner later on. So I'll just leave it to default. And we also have to add it in the plugins key. So let's do this. So plugins, let's add this. And let's not forget to run NPM run dev. And to use it, all we have to do is make a class with a div with a class of spinner. So I am going to do that. Let's go to we have to do it for each component. I'll just do it for one.

Let's go to we have to do it for each component. I'll just do it for one. And then I'll just edit in the rest. So we have to do dot-spinner here. Let's put a margin top on it as well. And that should do it. If I installed it correctly. Let's refresh. And you see a spinner there, cool. So I'll add it to these other three.

And you see a spinner there, cool. So I'll add it to these other three. Okay, so I've added it to the other three. And now everything should have spinners, cool. So one last thing that can improve performance is making use of caching. So let's go ahead and try to implement a cache for one of the API requests using the cache()->remember method. So let's copy this. And let's go to the popularGames one. So it's a popularGames.

And let's go to the popular games one. So it's a popular games. And I just want to simulate the API being even slower so I can demonstrate the cache. So I'm going to sleep here and say three seconds. So the popular games now should take even longer to load. So I'm going to refresh. You'll see that these ones load in but this one takes three seconds. Cool. So now if we cache that, let's actually put it right here. We can make use of Laravel's cache and we can bypass this completely if it's already

So now if we cache that, let's actually put it right here. We can make use of Laravel's cache and we can bypass this completely if it's already in the cache. So I'm going to paste that in. And let's give it a key here. So I want the key to be popularGames. And again, you can do this for the other components too, or anything that makes an API request. But I'm just going to do it for this component. So let's grab this, put it here. And let's cache it for 7 seconds.

So let's grab this, put it here. And let's cache it for seven seconds. And then we just want to return this. Okay. I'm going to erase this and it's returned what I just copied. And let me just re-indent this. Okay, now this will be stored in the cache. So if I refresh this now, it's still going to take long the first time. There you see it taking quite a while. And I have to import the cache.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟