For this third, and final, project, I have some starter code that I can use to develop a race simulator. From the front-end, visitors will be able to initiate a new race, select their racer, and “accelerate” (by clicking the screen) to see who wins the race. This project should be built on asynchronous functions to put the concepts from the last module to the test.
Today, I spent most of the day just familiarizing myself with the project and getting everything set up. It comes with an API that’s already built, but it’s a “black box” since you shouldn’t need to make any changes to the code. It’s harder to wrap my head around what it does, but it also feels like a much more realistic example.
I mostly read through the existing code, provided by Udacity. Then, the project has a list of
TODOs throughout the entire
index.js file. On the one hand, this is super convenient since it removes the logic of trying to determine what needs to happen next. On the other, it’s more structured than any of the projects and I feel a bit of constraint. I like it, though, because I imagine this is what it’s like working on, well, most things. I did have the thought, “This should probably be faster than the other projects” and then I just laughed 🙂
Today, I wrote up a bit of pseudo-code to help process the
TODOs listed throughout the project. As I started to convert that into actual code, I realized that I couldn’t go from top to bottom, but that I actually needed to start with the API calls.
For the first step of working on the API calls, I created a general method for fetch requests and started working on one of the specific calls that need to be made. Because this is my first time working with async programming and, especially, promises, I ran into a block as I started to implement this method in my first API request to get the racetrack ID.
At first, I was getting an error, but after a lot of
console.log-ing, I noticed that the request was indeed being fulfilled, but it’s returning a promise. Before moving on to the next step, I need to wrap my head around how to use the returned promise in a way that gets me the data I actually need from the API call.
Today was fun. I was actually overthinking the issue that I was running into last time. The method I’d written for the first API call I was working on – to get the track IDs – actually didn’t need anything more than, well, the request to the API. Basically, I just removed some extra code, made the call to the API, and returned that. Voilà, it worked.
Once I had that down, I set up the rest of the API calls, all of which were pretty similar. When I refreshed the page to make sure it worked, I was really surprised – and satisfied – to see all the players and tracks listed on the page already, thanks to the starter code.
From there, I started to work on the event handlers to help get the front-end working so visitors can create a new race. It was pretty straightforward, but the way the event handler was set up made it more complicated than I wanted to select the track and player. So I found a helpful code snippet that I then modified so that the target for the event included the entire element that encapsulated the button. This was a bit challenging for me to get working exactly how I wanted, since, by default, the code I was using then applied to the whole page. With some tweaks, I got it working.
For fun, I ended up adjusting the
data.json file, so I could add a theme to my races: Doctor Who. I made some customizations to the CSS (for the record, Tardis blue is
#003865), selected some characters from the universe, and gave some fun, Whovian track names. Ah! And I was also able to reuse some of the logic I created for updating the store in the Mars Rover project to handle the store for this project as well.
Today was spent going through the final
TODOs, which mostly included using
setInterval() to create the race, countdown to the race, and then actually run the race. It was straightforward, except for when it wasn’t.
Because these final methods were all asynchronous, I mostly ran into trouble with trying to figure out how to structure them – particularly, when to use
.then()and how to actually resolve the promise. I also had a few methods where I forgot that I either explicitly needed to pass in a parameter or use the
getState method to get the related information from the Store.
console.log()and moving it around throughout the code is really one of the most effective ways to debug what the heck is going on. There’s an oddity with the API for this project where you can’t just use the
race_id – it has to be
race_id - 1 in order for many of the API calls to work. I forgot to do this multiple times, and a simple
console.log() showed me that the ID was undefined. Of course it was!
Aside from all of that, the game is… actually working! It seems like there’s an error with the results, where it shows the same order no matter what. I need to investigate if this is coming from the API, or if I can resolve what’s happening in the code I have. Beyond that, the next step is just adding in error handling.
I just submitted my project! Today, I added some error handling. There honestly wasn’t too much, since the program came with some of its own error handling. I also created a function to render a more user-friendly error message on the front-end when there is an error. So now, instead of just console logging the issue, it’ll show an explanation and a button to retry starting the race.
Since adding the
.catch handlers was relatively straightforward, I then went ahead and used ESLint to clean up my code so that it’s standard. I still can’t tell what my preferences are (semi-colon? no semi-colon? spacing?) but I’d like to at least be consistent. That said, each time I’ve run ESHint, I end up fighting with JSLint in Visual Studio since they both run simultaneously. And every time I forget that I need to manually turn the second one off. It’s annoying, but hopefully this time the lesson sticks.
My project got rejected, but with some helpful code review! I missed an asynchronous method that still needed error handling. More importantly, the reviewer pointed out that there were a few parts of my code where I used let when I should have used const. This was so helpful. I realize I’ve been using them pretty haphazardly and not giving it a lot of thought, which is problematic. It was super helpful to realize I was doing that and to be able to fix it.
After making those small changes, I just got the feedback that my final project was accepted and I graduated from the whole Nanodegree course! I’m feeling pretty happy and excited about my progress here. Especially since I gave myself a lot more time to finish than I have in the past, and it went a lot more quickly.