owned this note
owned this note
Published
Linked with GitHub
# Callbacks and Promises
understanding the single-threaded [event loop](https://www.youtube.com/watch?v=8aGhZQkoFbQ) queue that drives all "events" (async function invocations). Concurrency is important when
- waiting on input/output as network request
- reading/writing from disk, or user input
(The callstack is a data structrue which records basically where in the program we are)
Two ways programs wait for IO:
- blocking
- Easy to write
- Uses multi-threading
- non-blocking/event-loop
- Single-threaded
- Hight-concurrency with low-memory consumption
![image](https://image.ibb.co/dKRQfd/2018_05_13_2_55_09.png)
What happens if you block in JavaSCript?
- alert/prompt/confirm
![alert](https://image.ibb.co/maj0Dy/2018_05_13_3_04_44.png)
## Callbacks
>Callbacks are just the name of a convention for using JavaScript functions... Instead of immediately returning some result like most functions, functions that use callbacks take some time to produce a result. The word 'asynchronous', aka 'async' just means 'takes some time' or 'happens in the future, not right now'. Usually callbacks are only used when doing I/O, e.g. downloading things, reading files, talking to databases, etc.
>
Callbacks can be one of two things:
- Callbacks can be any function that another function call
- Callbacks can be more explicitly an asynchronous callback
So how do we write concurrent code in JavaScript? --**Callbacks** -- Pass a function that will be aclled when the task is complete.
- ex: An on click event
- waiting for a network request
Pros:
- Great low-level abstraction
- Performant with low overhead
- Can do almost any async task with callbacks
Cons:
- Doing things in parallel is harder
- Give up constructs such as for/while and try/catch
- Error handling is difficult
- Code readability suffers and systems become hard to maintain
>Concurrency is related to how an application handles multiple tasks it works on. An application may process one task at at time (sequentially) or work on multiple tasks at the same time (concurrently).
>Parallelism is related to how an application handles each individual task. An application may process the task serially from start to end, or split the task up into subtasks which can be completed in parallel.
>An application can be concurrent, but not parallel. This means that it processes more than one task at the same time, but the tasks are not broken down into subtasks.
>
In all these cases, the function is acting as a "callback," because it serves as the target for the event loop to "call back into" the program, whenever that item in the queue is processed. ([event loop](https://www.youtube.com/watch?v=8aGhZQkoFbQ) 19:34)
## Callbacks as any function that another function call(A little bit about functional programming)
Callbacks are also called `higher order functions`.
- avoiding shared state, mutable data, and side-effects.
- declarative rather than imperative
- application state flows through pure functions
First of all we just take a look at some code:
```
funciton triple(x) {
return x*3
}
```
Yes, like most languages, JavaScript has functions.
But not every programming language can do this:
```
let triple = funciton (x) {
return x*3
}
```
We can create an annymous function and assign it to a variable.
So we can refactor the following snippet of code because functions in JS are `first class objects`. They can have properties and methods just like any other object, so you can pass `functions` as params into another function. Make this:
```
let calc = (num1, num2, calcType) => {
if(calcType === "add") {
return num1 + num2
} else (calctype === "multiply") {
return num1 * num2
}
}
```
More `functional style`:
```
let add = (a, b) =>
return a + b
let multiple = (a, b) =>
return a * b
let calc = (num1, num2, callback){
return callback(num1, num2)
}
calc(1,2,add)
```
this way, if the `add`, or `multiply` functions are from outside libraries, the best way to do it, is to make `calc` as abstract as possible.
## Codes that won't work
```
function getUserName() {
let name;
$.get('/users/123', (user) => {
name = user.name;
})
return name;
}
//It doesn't work
console.log('User Name:', getUserName())
```
## Chain tasks and paralleism with Callbacks
It's difficult to chain tasks and do parallelism
![](https://image.ibb.co/hXQFyy/2018_05_14_8_42_17.png)
Take three files and we want total the number of bytes in those files.
What if we don't want to do it one by one?
![](https://image.ibb.co/jGvzqd/2018_05_13_4_27_22.png)
We want to do it in parallel -- Read all the files and get the total number of bytes.--Naive version with no error handing
Keep tracking of `numFinished`
## Plus Error Handling
- spend more efforts checking if an async task failed
- lose try catch
![](https://image.ibb.co/eu9QVd/2018_05_13_4_32_12.png)
The minimal error handling -- just console log them out
## Readability Issues
When code readability is bad, we're more likely to let errors sneak in.
## Promises
A promise is an object that represents what the value will be when the operation finishes
- Easy chaining: sequential/parallel tasks
- Error handling
- composable: pass around a representation of future value
- control flow
So a promise style:
![](https://image.ibb.co/kjXZOy/2018_05_13_4_34_06.png)
We have two things: then and catch. We can attach a callback in then and execute it whenever the data is finished.
It's better because we can do some chaining:
![](https://image.ibb.co/buS13y/2018_05_13_4_34_44.png)
A simple example that uses set time out, wait for 1000 milliseconds, and then it fullfills the promise.
It's the same idea as a set timeout but in promise world.
So here we just wanna wait one second, log something, and then wait one second and log something.
We don't have nested callbacks here. It reads in a more sequential order.
In the first two then we return another promises that allows us to call another `.then`
## Flow control
We can easily combine sequential and parallel tasks to create advanced flows.
When have to do things in series, we wait for one to finish and then do the next. it's hard to do with callbacks.
![](https://image.ibb.co/i0bHbJ/2018_05_13_4_36_54.png)
1. User login,
2. and we want to fetch the friends of user, return a promise, which contain all the friends' ids(We can map through all the ids here and return an array of promises)
3. fetch all the friends' detail information
## Error Handling
- catch
- Exceptions will bubble up similiar to how it works in synchronous code
![](https://image.ibb.co/nGneqd/2018_05_13_4_58_56.png)
![](https://image.ibb.co/fh4QVd/2018_05_13_5_02_40.png)
## Pause functions like it's synchronous - Generator functions
![](https://image.ibb.co/eYtVwJ/2018_05_13_5_27_04.png)
## But we still need callbacks - Promises + Generators => How about async/await
It's a thin layer of syntax over Promises and Generators
![](https://image.ibb.co/eTLM3y/2018_05_13_5_50_28.png)
![](https://image.ibb.co/bt4g3y/2018_05_13_5_51_13.png)
![](https://image.ibb.co/c43xbJ/2018_05_13_5_54_44.png)
![](https://image.ibb.co/bS1iGJ/2018_05_13_5_56_09.png)
![](https://image.ibb.co/jRBiGJ/2018_05_13_5_56_56.png)
![](https://image.ibb.co/c8uQVd/2018_05_13_6_02_12.png)
![](https://image.ibb.co/gGaXAd/2018_05_13_6_03_52.png)
![](https://image.ibb.co/d3XOGJ/2018_05_13_6_04_14.png)
## References
https://www.youtube.com/watch?v=NsQ2QIrQShU
Async/Await: Modern Concurrency In JavaScript
https://codepen.io/serapath/pen/QrdooB?editors=0010
An example code from Alex async await vs callbacks
http://callbackhell.com/
how to avoid callback hell