Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add JS3 Week 2 prep content MOVED TO SPRINT 3 #403

Merged
merged 18 commits into from
Dec 27, 2023
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions assets/styles/04-components/columns.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// put anything side by side

.c-columns {
display: grid;
gap: var(--theme-spacing--gutter);
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}
71 changes: 71 additions & 0 deletions content/js3/blocks/asynchrony/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
+++
title = '⏳ Asynchrony : outside time'
headless = true
time = 30
facilitation = false
emoji= '🧩'
[objectives]
1="Define asynchrony"
2="Explain why we need asynchrony"
3="Identify an asynchronous method we have already used"
+++

We can handle latency using {{<tooltip title="asynchronous execution">}}run code in a different order.{{</tooltip>}} To understand asynchrony we first need to be clear about {{<tooltip title="synchronous execution">}}run code in the order it is written.{{</tooltip>}}.

We have written a lot of JavaScript programs that execute sequentially. This means that each line of code is run in order, one after the other.
{{<columns>}}

#### For example:

```js
console.log("first");
console.log("second");
console.log("third");
```

<--->

#### Outputs:

```console
first
second
third
```

{{</columns>}}
Each line of code is run in order. This is synchronous execution. We do this because JavaScript is {{<tooltip title="single threaded">}}
A single thread can do one thing at a time. JavaScript is a single threaded language.
{{</tooltip>}}.

When we call a function, the function will run to completion before the next line of code is executed. But what if we need to wait for something to happen? What if we need to wait for our data to arrive before we can show it? In this case, we can use asynchronous execution.

{{<tabs name="Event Loop">}}
{{<tab name="Event Listener">}}
We have already used asynchronous execution. We have defined eventListeners that _listen_ for events to happen, _then_ execute a callback function. But here's a new idea: eventListeners are part of the [Event API](https://developer.mozilla.org/en-US/docs/Web/API/Event). They are not part of JavaScript! 🤯

When you set an eventListener you are really sending a call to a Web API and asking it do something for you.

```js
const search = document.getElementById("search");
const waitForEvent = search.addEventListener("input", handleInput);
```

The callback `handleInput` cannot run until the user types. With `fetch`, the callback function cannot run until the data arrives. In both cases, we are waiting for something to happen before we can run our code.
{{</tab>}}
{{<tab name="Visualise the Event Loop">}}

<iframe src="http://latentflip.com/loupe/?code=JC5vbignYnV0dG9uJywgJ2NsaWNrJywgZnVuY3Rpb24gb25DbGljaygpIHsKICAgIGNvbnNvbGUubG9nKCdZb3UgY2xpY2tlZCB0aGUgYnV0dG9uIScpOyAgICAKfSk7Cgpjb25zb2xlLmxvZygiSGkhIik7Cgpjb25zb2xlLmxvZygiV2VsY29tZSB0byB0aGUgZXZlbnQgbG9vcCIpOw%3D%3D!!!PGJ1dHRvbj5DbGljayBtZSE8L2J1dHRvbj4%3D" width="100%" height="480px"></iframe>
{{</tab>}}
{{</tabs>}}

```mermaid
graph LR
TimeProblem[🗓️ Time Problem] --> |caused by| SingleThread[🧵 Single thread]
SingleThread --> |send tasks to| ClientAPIs
TimeProblem --> |solved by| Asynchrony[🛎️ Asynchrony]
Asynchrony --> | delivered with | ClientAPIs{💻 Client APIs}
ClientAPIs --> |like| setTimeout[(⏲️ setTimeout)]
ClientAPIs --> |like| eventListener[(🦻🏾 eventListener)]
ClientAPIs --> |like| fetch[(🐕 fetch)]
```
57 changes: 57 additions & 0 deletions content/js3/blocks/callbacks/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
+++
title = '🪃 Callbacks'
headless = true
time = 20
facilitation = false
emoji= '🧩'
[objectives]
1='Define a callback'
2="Sketch the event loop"
3="Predict the order of logged numbers using the event loop model"
+++

Consider this visualisation of an asynchronous program:

<iframe title="code running out of order and off the thread" src="http://latentflip.com/loupe/?code=c2V0VGltZW91dChmdW5jdGlvbiB0aW1lb3V0KCkgewogICAgY29uc29sZS5sb2coIjEiKTsKfSwgMjAwMCk7CnNldFRpbWVvdXQoZnVuY3Rpb24gdGltZW91dCgpIHsKICAgIGNvbnNvbGUubG9nKCIyIik7Cn0sIDUwMCk7CnNldFRpbWVvdXQoZnVuY3Rpb24gdGltZW91dCgpIHsKICAgIGNvbnNvbGUubG9nKCIzIik7Cn0sIDApOwo%3D!!!" width="100%" height="480px"></iframe>

When we call [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout) we send **a function call** to a client side Web API. The code isn't executing in our single thread any more, so we can run the next line. The countdown _is_ happening, but it's not happening _in our thread_.

When the time runs out, our Web API sends a message to our program to let us know. This is called an {{<tooltip title="event">}}An event is a signal that something has happened.{{</tooltip>}}. Our API sends its message to our {{<tooltip title="event loop">}}The event loop is a JavaScript mechanism that handles asynchronous callbacks.{{</tooltip>}}. And what message does the event loop send? It sends a **callback**. It sends _our_ call _back_.

{{<note type="tip" title="Our call is back">}}
A callback is our function call, sent back to us through the event loop.
{{</note>}}

{{<tabs name="Event Loop">}}
{{<tab name="Sketch your mental model">}}
**With a pen and paper**, draw a diagram of your mental model of the event loop.

Use your model to predict the order of logged numbers in the following code snippet:

```js
setTimeout(function timeout() {
console.log("1");
}, 2000);
setTimeout(function timeout() {
console.log("2");
}, 500);
setTimeout(function timeout() {
console.log("3");
}, 0);
```

{{</tab>}}
{{<tab name="Compare your model">}}

```mermaid
graph
Callbacks{{🪃 Callbacks}} --> |run on| SingleThread[🧵 Single thread]
SingleThread --> |handled by| EventLoop[🔁 Event Loop]
EventLoop --> |queues| Callbacks
SingleThread --> |send tasks to| ClientAPIs{💻 Client APIs}
ClientAPIs --> | send| Callbacks
```

Did yours look different? There are many ways to visualise the event loop. Work on building your own mental model that helps you predict how code will run.
{{</tab>}}
{{</tabs>}}
8 changes: 8 additions & 0 deletions content/js3/blocks/chaining/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
+++
title = 'Chaining Promises'
headless = true
time = 20
facilitation = false
emoji= '🧩'
[objectives]
+++
29 changes: 29 additions & 0 deletions content/js3/blocks/fetch/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
+++
title = 'fetch API'
headless = true
time = 20
facilitation = false
emoji= '🧩'
[objectives]
+++

Let's suppose we have a remote API hosted at the following url: "https://api-film-data.com".

We can use applications like Postman to make requests to APIs. However, we want to make a request for the film data using JavaScript. We can use `fetch` to make network requests in JavaScript. Let's take a look at how we can do this:

```js
const filmData = fetch("https://api-film-data.com/films");
```

`fetch` is a JavaScript function. We call `fetch` using the url of the remote API we wish to fetch data from. Once `fetch` has got the data then we want to store it in a variable so we can then use it in our application. Let's log this data:

```js
const filmData = fetch("https://api-film-data.com/films");
console.log(filmData);
```

However, if we log this variable we don't get an array of data. We get:

```console
Promise <pending>
```
62 changes: 62 additions & 0 deletions content/js3/blocks/fetching-data/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
+++
title = '🐕 Fetching data'
headless = true
time = 20
facilitation = false
emoji= '🧩'
[objectives]
1='Update a problem statement using web APIs to fetch data'
+++

So far we have displayed films data stored in our JavaScript code. But real applications fetch data from servers over the internet. We can restate our problem as follows:

> _Given_ a **web API that serves** film data
> _When_ the page first loads
> _Then_ the page should fetch and display the list of film data, including the film title, times and film certificate

We will use [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch), a {{<tooltip title="client side Web API">}}
A client side Web API lives in the browser. They provide programmatic access _to_ built-in browser functions _from_ JavaScript. {{</tooltip>}}. Fetch will fetch our data from the {{<tooltip title="server side Web API">}}
A server side Web API lives on a server. They provide programmatic access _to_ data or functions stored on the server _from_ JavaScript. {{</tooltip>}}.

_Using_ fetch is simple. But we want to understand what is happening more completely. So let's take ourselves on a journey through time.

<details>
<summary>👉🏾 Unfurl to see the journey</summary>

```mermaid
graph TD
fetch[(🐕 fetch)] --> |sends a| Request{📤 Request}
Request --> |has a latency| TimeProblem[🗓️ Time Problem]
Request --> |to| ServerAPIs
fetch --> |is a| ClientAPIs

TimeProblem --> |caused by| SingleThread[🧵 Single thread]
Callbacks{{🪃 Callbacks}} --> |run on| SingleThread
SingleThread --> |handled by| EventLoop[🔁 Event Loop]
EventLoop --> |queues| Callbacks
SingleThread --> |send tasks to| ClientAPIs
SingleThread --> |handled by| Asynchrony

TimeProblem --> |solved by| Asynchrony[🛎️ Asynchrony]
Asynchrony --> |delivered with| Promise{{🤝 Promises}}
Asynchrony --> | delivered with | ClientAPIs
Promise --> |resolve to a| Response{📤 Response}
Promise --> |join the| EventLoop{{Event Loop 🔁}}
Promise --> |syntax| async{{🏃‍♂️ async}}
async --> |syntax| await{{📭 await}}
await --> |resolves to| Response
Response ---> |sequence with| then{{✔️ then}}


WebAPIs((🧰 Web APIs)) --> |live in your browser| ClientAPIs{💻 Client side APIs}
ClientAPIs --> |like| setTimeout[(⏲️ setTimeout)]
ClientAPIs --> |like| eventListener[(🦻🏾 eventListener)]
WebAPIs --> |live on the internet| ServerAPIs{🌐 Server side APIs}
ServerAPIs --> |serve our| Data[(💾 Data)]
Data --> |as a| Response

```

😵‍💫 This is a lot to take in. Let's break it down and make sense of it.

</details>
26 changes: 26 additions & 0 deletions content/js3/blocks/internet/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
+++
title = 'How the internet works'
headless = true
time = 20
facilitation = false
emoji= '🧩'
[objectives]
1='Describe what happens when a user enters a url into a browser'
2='Explain the purpose of the HTTP protocol'
3='Define a GET request in the HTTP protocol'
+++

We've been using the internet for years, but how does it actually work? What happens when you type a URL into a browser? How does the browser know where to go? How does it know what to show? How does it know how to show it?

{{<tabs name="How the internet works playlist">}}
{{<tab name="What is the internet">}}
{{<youtube>}}https://www.youtube.com/watch?v=Dxcc6ycZ73M
{{</youtube>}}
{{</tab>}}
{{<tab name="Understanding networks">}}
{{<youtube>}}https://www.youtube.com/watch?v=ZhEf7e4kopM{{</youtube>}}
{{</tab>}}
{{<tab name="HTTPS & HTML">}}
{{<youtube>}}https://www.youtube.com/watch?v=kBXQZMmiA4s{{</youtube>}}
{{</tab>}}
{{</tabs>}}
21 changes: 21 additions & 0 deletions content/js3/blocks/latency/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
+++
title = '🗓️ Latency'
headless = true
time = 5
facilitation = false
emoji= '🧩'
[objectives]
1='Define latency'
+++

```mermaid
graph LR
fetch[(🐕 fetch)] --> |sends a| Request{📤 Request}
Request --> |has a latency| TimeProblem[🗓️ Time Problem]
```

Once we are taking our data on a journey over a network, we introduce the problem of latency. Latency is the time taken for a request to traverse the network.

> 💡 Network latency is travel time.

Why is latency a problem? Because it means we need to **wait** for our data. But if we stopped our program to wait for data, then we wouldn't be able to do anything else. We need to handle this time problem. Programming often involves time problems, and latency is just one of them.
9 changes: 9 additions & 0 deletions content/js3/blocks/promises/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
+++
title = 'What is a Promise?'
headless = true
time = 30
facilitation = false
emoji= '🧩'
[objectives]
1=''
+++
9 changes: 9 additions & 0 deletions content/js3/blocks/then/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
+++
title = 'Making sense of .then()'
headless = true
time = 30
facilitation = false
emoji= '🧩'
[objectives]
1=''
+++
53 changes: 53 additions & 0 deletions content/js3/blocks/using-fetch/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
+++
title = '🌐 Requesting from a server side API'
headless = true
time = 20
facilitation = false
emoji= '🧩'
[objectives]
1="List 4 preceding concepts of asynchronous programming in JavaScript"
2="Identify unknown concepts still to be learned"
3="Fetch data from a server side API"
+++

So now we have these pieces of our giant concept map

🗓️ we know that sending 📤 requests over a network takes time
🧵 we know that we should not stop our program to wait for data
📤 we know that we can send a request using `fetch()`
🐕 we know that `fetch` is a 💻 client side 🧰 Web API
🫱🏿‍🫲🏽 we know that `fetch` returns a `Promise`? (...this last one is pending)

But we still don't know how to use `fetch` to get data from a server side API. Let's find out. Run this code in the console in your browser.

```js
const endpoint = "//curriculum.codeyourfuture.io/dummy-apis/films.json";
const fetchPromise = fetch(endpoint);
fetchPromise.then((response) => {
console.log(response.json());
});
```

So that's how we use `fetch` to get data from a server side API. In [our filterFilms code](https://curriculum.codeyourfuture.io/filterfilms), we can replace the films array with the data fetched from the server.

```js
// Begin with an empty state
const state = {
films: [],
};
// Data
const endpoint = "//curriculum.codeyourfuture.io/dummy-apis/films.json";

const fetchFilms = async () => {
const response = await fetch(endpoint);
return await response.json();
}; // our async function returns a Promise

fetchFilms().then((films) => {
render(filmContainer, films); // when
});
```

🐕 `fetch` returns a 🫱🏿‍🫲🏽 ‍`Promise`; the 🫱🏿‍🫲🏽 `Promise` fulfils itself with a 📥 response; the response contains our 💾 data.

We will dig into this syntax: `Promises`, `async`, `await`, and `then` in our next sprint and complete our concept map.
3 changes: 3 additions & 0 deletions content/js3/prep/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ menu_level = ['module']
weight = 1
backlog= 'Module-JS3'
[[blocks]]
name="How the internet works"
src="js3/blocks/internet"
[[blocks]]
name="Technical Writing 101"
src="https://github.com/CodeYourFuture/Module-JS3/issues/243"
+++
Expand Down
16 changes: 15 additions & 1 deletion content/js3/sprints/3/prep/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,21 @@ menu_level = ['sprint']
weight = 1
backlog= 'Module-JS3'
backlog_filter= 'Week 3'

[[blocks]]
name="Fetching data"
src="js3/blocks/fetching-data"
[[blocks]]
name="Latency"
src="js3/blocks/latency"
[[blocks]]
name="Asynchrony"
src="js3/blocks/asynchrony"
[[blocks]]
name="Callbacks"
src="js3/blocks/callbacks"
[[blocks]]
name="Using .fetch()"
src="js3/blocks/using-fetch"
[[blocks]]
name="Product MVP and features"
src="https://cyf-pd.netlify.app/blocks/define-your-products-mvp/readme/"
Expand Down
Loading