## JavaScript First Steps ### A [FrontendMasters](https://frontendmasters.com) course by [AnjanaVakil](https://twitter.com/AnjanaVakil) [anjana.dev/javascript-first-steps](https://anjana.dev/javascript-first-steps)
# PART 3 -- ### Goals - Use while loops to repeat actions - Differentiate asynchronous from syncronous code - Use asynchronous functions to fetch data - Use fancy modern JS syntax - Learn real-world techniques for debugging & error handling - Play with doggos! --- Next project: Adapt our quiz for something cuter
-- [Doggo Fetch](./3-doggofetch-finished.html) - Go to [anjana.dev/javascript-first-steps](https://anjana.dev/javascript-first-steps) - In Part 3, go to the [starter](./3-doggofetch-starter.html) file - Save & open in your text editor --
## Loops ...continued
-- ### `while` loops let us run a chunk of code over & over if a `(condition)` is true ```js let fiveRandomNumbers = []; while (fiveRandomNumbers.length < 5) { fiveRandomNumbers.push(Math.random()); } ``` -- Don't use `while (true)` unless you want to see your computer burn! ```js while (true) { console.log("I am wasting resources infinitely"); } ```
-- ### Exercise In the Doggo Fetch starter, follow TODO 1 to fill in the `getMultipleChoices` function using a `while` loop
## (A)synchronous code
Time & JS are ...frenemies -- Usually, our JS code does things that are very quick ```js console.log("This will print in a New York minute"); console.log("This will print one New York minute later"); ``` So JS can usually run straight through our program "synchronously" -- But when we need to do something that takes a long time
we still want the web browser to keep working -- JS can only do one task at a time ("single-threaded")
JS says: *I cannot text you with a drink in my hand, eh*
Metaphor courtesy Daniel Higginbotham
-- So when we give JS a task that takes a while, it doesn't stop and wait ```js console.log("This will print first"); setTimeout(() => console.log("This will print third"), 1000); console.log("This will print second"); ``` it adds the slow task to a "TODO list" and keeps on running our program The task runs some time later, "asynchronously" -- Some things that take time: - Waiting for user events - Asking a user to pick a file - Getting permission to access the camera/mic - *Loading data from the interwebs* -- Another thing that takes time: - Learning about asynchronous JS Add it to your TODO list! - [MDN: Introducing Asynchronous JS](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Introducing) - [Philip Roberts: What the heck is the event loop anyway?](https://www.youtube.com/watch?v=8aGhZQkoFbQ)
## Fetching data
-- URLs point to resources on the web `https://images.dog.ceo/breeds/bluetick/n02088632_924.jpg`
-- APIs provide URLs that point at data we care about `https://dog.ceo/api/breed/hound/list` ```json { "message": [ "afghan", "basset", "blood", "english", "ibizan", "plott", "walker" ], "status": "success" } ``` -- `fetch()` lets us use JS to load data from APIs ```js fetch("https://dog.ceo/api/breed/hound/list") ``` But if we run it in the console, we see something weird...
## Promises
-- It takes time to fetch data from the network ```js >> fetch("https://dog.ceo/api/breed/hound/list") Promise {
: "pending" } ``` So JS writes us an "IOU" for the data value it doesn't have yet aka a `Promise` of a value -- Promises can be in 3 possible states: - `pending`: still waiting for the value, hang tight - `fulfilled` (aka "resolved"): finally got the value, all done - `rejected`: sorry couldn't get the value, all done It takes time for Promises to resolve, so they are "asynchronous" -- JS adds the task to the TODO list and keeps running our program
But our program needs the data, we want JS to stop and wait for the Promise to resolve
## `await`
`await` lets us tell JS to stop and wait for an asynchronous operation to finish -- In the case of a Promise, it waits for it to resolve before continuing with our code ```js let response = await fetch("https://dog.ceo/api/breed/hound/list"); console.log(response); ``` The Promise we get from `fetch()` resolves to a `Response` object -- It's `body` contains the data we care about
But we have to read the body somehow -- Calling the `.json()` method on the response parses its body as a JSON object ```js response.json() ``` But that gives us another Promise! -- This is getting frustrating...
But don't give up! -- Let's try again, this time `await`ing the JSON Promise too ```js let response = await fetch("https://dog.ceo/api/breed/hound/list"); let body = await response.json(); ``` -- `success`!!!
...but now we have to use the data!
## Destructuring
Illustration by Sara Vieira
-- Destructuring is a fancy way of declaring multiple variables at once By "extracting" values from an object with their property names ```js let {name, nickname} = spices[0]; ``` -- If we only care about some of the properties, we can omit the others ``` let {nickname} = spices[2]; ``` -- We can also destructure Arrays, assigning variables for their items ```js const [baby, ginger, scary, sporty, posh] = spices; ``` -- We can ignore the values in the array we don't need ```js const [emma, geri] = spices; ``` We can use commas to "skip" values ```js const [,,melB] = spices; ``` -- We can use `...` to collect remaining values ```js const [babySpice, ...adultSpices] = spices; ``` -- ### Exercise In your Doggo Fetch file, follow TODO 2 to complete the `getBreedFromURL` function with destructuring The string method `.split()` will be useful - it returns an array of substrings by splitting a string at a certain character: ```js let [first, middle, last] = "Anjana Sofia Vakil".split(" "); ``` -- *Back to our fetched data...* Let's destructure the data we fetched so that we can use it! ```js let { message } = body; ``` We only really care about the `message`
## `async` functions Let's wrap all our async fetching & parsing code up into a function!
-- If we try to `await` something in a regular `function`... ```js function fetchResponse(url) { const response = await fetch(url); return response; } ``` JS doesn't allow it -- We need to make it an `async function` ```js async function fetchResponse(url) { const response = await fetch(url); return response; } ``` This tells JS to expect to `await` async operations inside the function -- ### Exercise In your Doggo Fetch file, follow TODO 3 to fill in the `async function` body Use what we've learned about how to fetch, parse, and extract the data we need!
## Putting our doggos to bed Let's finish up the last TODOs, 4 & 5 They require you to practice skills you've learned so far -- We're up & running with JS!!!
Amazing job!
## JS in the wild
-- There is *lots* more we could say about JS Let's talk about a few other concepts relevant to using JS in real life
## Modules
Modules let us split big codebases across multiple files -- ### Top-level `await` At the end of our doggo program we had to use `await` *outside* of a function This isn't usually possible in JS... -- Take a closer look at our `script` tag: ```html ``` JS *modules* work differently from JS *scripts* -- One difference is that we can't use `await` outside of a function in a script ```html ``` -- ### Module scope Another difference is that modules create their own scope
Try loading the page and accessing the `BREEDS` variable we declare in the module -- ### `import` && `export`
`export` lets us expose variables from our module's scope to the outside world ```js // myModule.js const veryUsefulFunction = () => "I came from a module"; export { veryUsefulFunction }; ``` -- `import` lets us use an exposed variable from another module ```js // otherModule.js import { veryUsefulFunction } from './myModule.js' veryUsefulFunction(); ``` -- There's lots more to learn about modules! [MDN > JS Guide > JS Modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules)
## Debugging
-- A certainty of coding (especially in JS):
Stuff. Will. Go. Wrong! -- `console.log()` (or `.warn()` or `.error()`) is one way to understand what's happening when your program runs ```js function whyIsntThisWorking(input) { console.log("Well at least we got this far"); console.log(input); return thingThatDoesntWork(input); } ``` -- You can also use the browser's debugger to *pause* JS and inspect what's happening ```js function whyIsntThisWorking(input) { debugger; return thingThatDoesntWork(input); } ``` The `debugger` statement creates a *breakpoint* where JS will pause and let you look around -- Different browsers' debuggers work differently - [Firefox](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools#the_javascript_debugger) - [Chrome](https://developer.chrome.com/docs/devtools/javascript/) - [Safari](https://support.apple.com/guide/safari-developer/debugging-overview-devd24689f72/mac)
## Error handling Once we've discovered where in our program an error is likely, we can do something about it!
-- Usually errors will cause JS to stop running our code ```js thisThrowsAnError(); console.log("I'll never get here"); ``` Sometimes that's appropriate and what we want JS to do -- But sometimes we might want to try again, or try a different way
Or if it was optional, just skip it and move on with our (program's) lives -- `try` lets us "watch out" for potential errors its friend `catch` lets us manage errors when they occur ```js try { thisMightThrowAnError(); } catch (error) { console.error("As if! Error:", error); console.log("Whatever, let's press on anyway"); } console.log("still rollin' with the homies"); ``` -- Read all about it! [MDN: JS > Statements > try...catch](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch)
# RECAP -- Look at all your badass new JS magic powers!
-- ### Values ### Arrays ### Objects -- ### Variables ### Functions ### Scope -- ### Events ### Conditionals ### Loops -- ### Asynchronous code ### Fancy syntax ### Real-world skills -- Amazing job!!
## Next steps - Dig deeper with more FrontendMasters courses - Refine your mental model with [Just JavaScript](https://justjavascript.com/) by Dan Abramov and Maggie Appleton - Explore & investigate on [MDN](developer.mozilla.org) & elsewhere - Keep tinkering!
## Thank you! Thanks to Marc Grabanski & Daniel Higginbotham for their help in creating this course Slides powered by [reveal.js](https://revealjs.com)