Skip to content

Commit f082791

Browse files
committed
Including repl examples and fixing typos
1 parent c5efb45 commit f082791

File tree

2 files changed

+56
-9
lines changed

2 files changed

+56
-9
lines changed

control-flow/index.md

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ JavaScript programs are made up of series of instructions. When our programs run
99

1010
Consider the following code.
1111

12+
<div class="repl-code">
13+
1214
```
1315
console.log('Clean teeth');
1416
setTimeout(() => {
@@ -17,6 +19,8 @@ setTimeout(() => {
1719
console.log('Wash face and hands');
1820
```
1921

22+
</div>
23+
2024
In the above code our compiler goes through each line executing each instruction. First it logs `Clean teeth`. Then it doesn't hang around for the `setTimeout`, it simply carries on and logs `Wash face and hands`. Then (a small moment later), it will log `Use lavatory`.
2125

2226
This is not what we want. We'll have to go wash our hands again. In production code, even worse things can happen.
@@ -33,6 +37,8 @@ Let's say we have to get some data from an external service. We don't know how l
3337

3438
To simulate this I've created a `randomDelayedResponse` function that will return a response after an unspecified amount of time.
3539

40+
<div class="repl-code">
41+
3642
```
3743
function randomDelayedResponse(text) {
3844
// Using a timeout here for the sake of simulating an external request
@@ -47,10 +53,14 @@ const output = randomDelayedResponse('Hello');
4753
console.log(output); // undefined
4854
```
4955

56+
</div>
57+
5058
Notice that the final line above returns `undefined`. This is because the `randomDelayedResponse` line is _non_blocking_ and hasn't returned anything to `output` before we then try to apply `console.log` to it.
5159

5260
We need to wait until the response is ready. One way is to pass our `console.log` in to `randomDelayedResponse` as a function.
5361

62+
<div class="repl-code">
63+
5464
```
5565
function randomDelayedResponse(text, callback) {
5666
// Using a timeout here for the sake of simulating an external request
@@ -64,12 +74,16 @@ const output = randomDelayedResponse('Hello', text => console.log(text)); // out
6474
console.log(output); // still empty
6575
```
6676

77+
</div>
78+
6779
We pass the function `text => console.log(text)` as the second parameter, and this function is then called after the `setTimeout`.
6880

6981
This might be reasonable in simple situations but it's easy for callbacks to get out of control. For example, if we have many different calls to this slow function that need to be run in order. To achieve this control we need to nest further.
7082

7183
To show many responses, consider the following code. If we ran them beside each other, the output would not be reliable.
7284

85+
<div class="repl-code">
86+
7387
```
7488
function randomDelayedResponse(text, callback) {
7589
const timeOut = Math.floor(Math.random() * 100) + 1;
@@ -85,10 +99,14 @@ randomDelayedResponse(4, console.log); // outputs 4
8599
// Who will win?
86100
```
87101

102+
</div>
103+
88104
Here we pass in the function `console.log` as the second argument which is then run as `callback(text)` to log the output.
89105

90106
While the code does run in order and run the `randomDelayedResponse` function with the right sequence of inputs, the random delays mean they won't be logged in order. We can run the above code multiple times and the result is never predictable. Each call to the function is _asynchronous_, in that the results do not arrive in order. To create a predictable, _synchronous_ flow using callbacks we'd need to nest them.
91107

108+
<div class="repl-code">
109+
92110
```
93111
function randomDelayedResponse(text, callback) {
94112
const timeOut = Math.floor(Math.random() * 100) + 1;
@@ -111,6 +129,8 @@ randomDelayedResponse(1, text => {
111129
}); // outputs "1 2 3 4"
112130
```
113131

132+
</div>
133+
114134
Structuring these callbacks outputs the numbers in the correct order. However when we use `callbacks` the code can become difficult to understand and maintain. This might be suitable in simple cases. Though if we find ourselves nesting multiple levels deep we should look for other ways to control the flow.
115135

116136
Let's look at one such alternative.
@@ -134,6 +154,8 @@ ourPromiseFunction() // returns a promise that will resolve or reject
134154

135155
We can rewrite our runner example using promises like so:
136156

157+
<div class="repl-code">
158+
137159
```
138160
function randomDelayedResponse(text, callback) {
139161
return new Promise((resolve, reject) => {
@@ -169,6 +191,8 @@ randomDelayedResponse(1)
169191
// outputs "1 2 3 4"
170192
```
171193

194+
</div>
195+
172196
Running the above code should output the correct order, albeit with random delays between each number.
173197

174198
In the above example we shouldn't see any errors - but if you want to adjust one of the `andomDelayedResponse()` calls to pass in no data, it should `reject` and the `catch` block will log the error.
@@ -179,6 +203,8 @@ Promises remove the nesting and give us easier to read code. Let's look at a thi
179203

180204
The third approach is built on top of the existing _promises_ approach and results in even simpler code. With `async` and `await` we can write code that feels a lot more like our usual top-down code. It works by telling our commands to wait when we need them to. Let's rewrite our _who will win?_ example from above.
181205

206+
<div class="repl-code">
207+
182208
```
183209
function randomDelayedResponse(text, callback) {
184210
return new Promise((resolve, reject) => {
@@ -215,6 +241,8 @@ async function runTheRace() { // put `async` before the function call
215241
runTheRace();
216242
```
217243

244+
</div>
245+
218246
In the above we have replaced the series of `.then()` calls with an `async` function. It's still making use of a _promise_ but when we want to wait for the promise we simply place `await` before the asynchronous function. The code execution order is preserved.
219247

220248
You may be wondering how we handle errors here. One approach is to use the `try/catch` method. We'll be covering that and more in the [error handling section]({{ "/error-handling/" | url }}).
@@ -227,6 +255,8 @@ Generally you should try to aim for the `async/await` approach when possible. It
227255

228256
Given the following code, how would you change it so that the results always outputs `hello world`? Can you make it work using all 3 of the above approaches?
229257

258+
<div class="repl-code">
259+
230260
```
231261
function hello() {
232262
const timeOut = Math.floor(Math.random() * 100) + 1;
@@ -243,14 +273,19 @@ function world() {
243273
}
244274
```
245275

276+
</div>
277+
246278
## Suggested solution
247279

248280
<button class="show-solution" onClick={showSolution()}>Show solution</button>
249281

250282
<div class="solution hidden">
251283

284+
<div class="repl-code">
285+
252286
```
253-
# Callbacks
287+
// Callbacks
288+
254289
function hello(callback) {
255290
const timeOut = Math.floor(Math.random() * 100) + 1;
256291
setTimeout(() => {
@@ -260,17 +295,21 @@ function hello(callback) {
260295
}
261296
262297
function world() {
263-
const timeOut = Math.floor(Math.random() _ 10) + 1;
298+
const timeOut = Math.floor(Math.random() * 100) + 1;
264299
setTimeout(() => {
265300
console.log('world');
266-
}, timeOut _ 10);
301+
}, timeOut);
267302
}
268303
269304
hello(world);
270305
```
271306

307+
</div>
308+
309+
<div class="repl-code">
310+
272311
```
273-
# Promises
312+
// Promises
274313
275314
function hello() {
276315
return new Promise((resolve, reject) => {
@@ -301,8 +340,12 @@ hello()
301340
302341
```
303342

343+
</div>
344+
345+
<div class="repl-code">
346+
304347
```
305-
# Async / Await
348+
// Async / Await
306349
307350
function hello() {
308351
return new Promise((resolve, reject) => {
@@ -324,17 +367,21 @@ function world() {
324367
325368
async function helloWorld() {
326369
try {
327-
const hello = await hello();
328-
const world = await world();
329-
console.log(`${hello} ${world}`);
370+
const helloOutput = await hello();
371+
const worldOutput = await world();
372+
console.log(`${helloOutput} ${worldOutput}`);
330373
} catch (err) {
331374
throw(err);
332375
}
333376
}
377+
378+
helloWorld();
334379
```
335380

336381
</div>
337382

383+
</div>
384+
338385
## Common Classes and Functions
339386

340387
### Callback pattern

js/main.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
function checkForReplLinks() {
44
const replCode = document.querySelectorAll('.repl-code');
55
[...replCode].forEach(code => {
6-
const codeText = encodeURI(code.innerText);
6+
const codeText = encodeURIComponent(code.innerText);
77
const link = document.createElement('a');
88
link.title = 'Run this code in the REPL';
99
link.innerText = 'Run this code in the REPL';

0 commit comments

Comments
 (0)