6ms: 2
10ms: hello
hideSummary:
summary: This model of javascript isn't enough for us to understand the async nature of our code,
Something is missing.
---
layout: false
# Browser API / Features
The browser provides us many features to handle code OUTSIDE of javascript
-
DOM (Document Object Model)
-
Timer (WindowOrWorkerGlobalScope)
-
XHR (Xml Http Request)
-
fetch (WindowOrWorkerGlobalScope)
-
local storage
-
console
- And a lot more...
developer.mozilla.org/en-US/docs/Web/API
---
layout:true
name: browser API
template: asyncjs
mainTitle: Browser API (Features)
BrowserFeature:
browserTime:
browserCallbackName:
browserStatus:
cbTaskHiddenClass: transparent
eventLoopHiddenClass: hide
taskClass: hide
microTaskClass: hide
Browser API
{{BrowserFeature}}
{{browserTime}}
{{browserCallbackName}}
{{browserStatus}}
---
template: brows API
mark1:*
memoryVariables:
---
template: brows API
mark2:*
memoryVariables:
---
template: brows API
mark3:*
threadCommnads:
console.log(1)
memoryVariables:
consoleLogs:
1ms: 1
---
template: brows API
mark4:*
threadCommnads:
console.log(1)
setTimeout(printHello,0)
memoryVariables:
consoleLogs:
1ms: 1
BrowserFeature: Timer
browserTime: 0ms
browserCallbackName: printHello
browserStatus: Complete: false
---
template: brows API
mark2:*
mark5:*
callStackMethods:
logUser()
threadCommnads:
console.log(1)
setTimeout(printHello,0)
logUser('Sagiv')
memoryVariables:
consoleLogs:
1ms: 1
4ms: Sagiv
cbTaskHiddenClass:
taskClass:
BrowserFeature: Timer
browserTime:0ms
browserCallbackName: printHello
browserStatus: Complete: true
---
template: brows API
mark6:*
threadCommnads:
console.log(1)
setTimeout(printHello,0)
logUser('Sagiv')
memoryVariables:
consoleLogs:
1ms: 1
4ms: Sagiv
6ms: 2
cbTaskHiddenClass:
taskClass:
eventLoopHiddenClass:
BrowserFeature: Timer
browserTime:0ms
browserCallbackName: printHello
browserStatus: Complete: true
---
template: brows API
threadCommnads:
console.log(1)
setTimeout(printHello,0)
logUser('Sagiv')
memoryVariables:
consoleLogs:
1ms: 1
4ms: Sagiv
6ms: 2
cbTaskHiddenClass:
taskClass:
eventLoopHiddenClass:
BrowserFeature: Timer
browserTime:0ms
browserCallbackName: printHello
browserStatus: Complete: true
---
template: brows API
mark1:*
taskClass:
eventLoopHiddenClass:
callStackMethods:
printHello()
threadCommnads:
console.log(1)
setTimeout(printHello,0)
logUser('Sagiv')
memoryVariables:
consoleLogs:
1ms: 1
4ms: Sagiv
6ms: 2
10ms: hello
---
template: brows API
taskClass:
eventLoopHiddenClass:
threadCommnads:
console.log(1)
setTimeout(printHello,0)
logUser('Sagiv')
memoryVariables:
consoleLogs:
1ms: 1
4ms: Sagiv
6ms: 2
10ms: hello
---
template: questions
---
template: chapter
number: 3
title: I'll fetch, that's a Promise!
subtitle: Wearing 2 hats
---
layout: true
name: promise
mark1:
mark2:
mark3:
mark4:
mark5:
mark6:
mark7:
mark8:
# Promise
```
{{mark1}}function displayUser(user) { console.log(user); }
{{mark2}}function printHello() { console.log('hello'); }
{{mark3}}function block500ms() { /* some blocking logic for 500ms (while loop?) */ }
{{mark4}}setTimeout(printHello, 0);
{{mark5}}const userFromServer = fetch('https://d.com/user/1'); // returns 'sagiv'
{{mark6}}userFromServer.then(displayUser);
{{mark7}}block500ms();
{{mark8}}console.log('global')
```
---
template: promise
---
layout: true
name: promise context
class: promise-context
template: promise
memoryVariables:
consoleLogs:
threadCommnads:
callStackMethods:
cbTaskHiddenClass: transparent
taskClass:
eventLoopHiddenClass:
microTaskClass: hide
microTaskQueClass: transparent
BrowserFeature:
browserTime:
browserCallbackName:
browserStatus:
displayUser: transparent
printHello: transparent
block500ms: transparent
promiseObj: transparent
promiseThen: transparent
timer: transparent
timerStatus: false
xhr: transparent
xhrStatus: false
{{callStackMethods}}
global()
Browser API
Feature: Timer
Wait: 0ms
Callback: printHello
Complete: {{timerStatus}}
Feature: XHR
URL: https://d.com/user/1
Method: GET
On Complete: displayUser
Complete: {{xhrStatus}}
---
template: promise context
mark1: *
threadCommnads:
function displayUser(...
displayUser:
---
template: promise context
mark2: *
threadCommnads:
function displayUser(...
function printHello(...
displayUser:
printHello:
---
template: promise context
mark3: *
threadCommnads:
function displayUser(...
function printHello(...
function block500ms(...
displayUser:
printHello:
block500ms:
---
template: promise context
mark4: *
threadCommnads:
function displayUser(...
function printHello(...
function block500ms(...
setTimeout(printHello, 0)
displayUser:
printHello:
block500ms:
timer:
taskClass:
---
template: promise context
mark5: *
threadCommnads:
function displayUser(...
function printHello(...
function block500ms(...
setTimeout(printHello, 0)
const userFromServer = fetch('https://d.com/user/1')
displayUser:
printHello:
block500ms:
promiseObj:
timer:
timerStatus: true
taskClass:
cbTaskHiddenClass:
xhr:
---
template: promise context
mark6: *
threadCommnads:
function displayUser(...
function printHello(...
function block500ms(...
setTimeout(printHello, 0)
const userFromServer = fetch('https://d.com/user/1')
displayUser:
printHello:
block500ms:
promiseObj:
timer:
timerStatus: true
taskClass:
cbTaskHiddenClass:
xhr:
promiseThen:
---
template: promise context
mark7: *
threadCommnads:
function displayUser(...
function printHello(...
function block500ms(...
setTimeout(printHello, 0)
const userFromServer = fetch('https://d.com/user/1')
block500ms()
displayUser:
printHello:
block500ms:
promiseObj:
timer:
timerStatus: true
taskClass:
cbTaskHiddenClass:
xhr:
promiseThen:
---
template: promise context
mark8: *
threadCommnads:
function displayUser(...
function printHello(...
function block500ms(...
setTimeout(printHello, 0)
const userFromServer = fetch('https://d.com/user/1')
block500ms()
displayUser:
printHello:
block500ms:
promiseObj:
timer:
timerStatus: true
taskClass:
cbTaskHiddenClass:
xhr:
promiseThen:
xhrStatus: true
consoleLogs:
global
---
template: promise context
threadCommnads:
function displayUser(...
function printHello(...
function block500ms(...
setTimeout(printHello, 0)
const userFromServer = fetch('https://d.com/user/1')
block500ms()
displayUser:
printHello:
block500ms:
promiseObj:
timer:
timerStatus: true
taskClass:
microTaskClass:
microTaskQueClass:
cbTaskHiddenClass:
xhr:
promiseThen:
xhrStatus: true
consoleLogs:
global
---
template: promise context
mark1: *
threadCommnads:
function displayUser(...
function printHello(...
function block500ms(...
setTimeout(printHello, 0)
const userFromServer = fetch('https://d.com/user/1')
block500ms()
displayUser(sagiv)
**EXECUTION CONTEXT **
displayUser:
printHello:
block500ms:
promiseObj:
timer:
timerStatus: true
taskClass:
microTaskClass:
cbTaskHiddenClass:
xhr:
promiseThen:
consoleLogs:
global
sagiv
callStackMethods:
displayUser()
---
template: promise context
threadCommnads:
function displayUser(...
function printHello(...
function block500ms(...
setTimeout(printHello, 0)
const userFromServer = fetch('https://d.com/user/1')
block500ms()
displayUser(sagiv)
displayUser:
printHello:
block500ms:
promiseObj:
timer:
timerStatus: true
taskClass:
microTaskClass:
cbTaskHiddenClass:
xhr:
promiseThen:
consoleLogs:
global
sagiv
callStackMethods:
---
mark2: *
template: promise context
threadCommnads:
function displayUser(...
function printHello(...
function block500ms(...
setTimeout(printHello, 0)
const userFromServer = fetch('https://d.com/user/1')
block500ms()
displayUser(sagiv)
printHello()
**EXECUTION CONTEXT **
displayUser:
printHello:
block500ms:
promiseObj:
timer:
timerStatus: true
taskClass:
microTaskClass:
xhr:
promiseThen:
consoleLogs:
global
sagiv
callStackMethods:
printHello()
---
mark2: *
template: promise context
threadCommnads:
function displayUser(...
function printHello(...
function block500ms(...
setTimeout(printHello, 0)
const userFromServer = fetch('https://d.com/user/1')
block500ms()
displayUser(sagiv)
printHello()
**EXECUTION CONTEXT **
displayUser:
printHello:
block500ms:
promiseObj:
timer:
timerStatus: true
taskClass:
microTaskClass:
xhr:
promiseThen:
consoleLogs:
global
sagiv
hello
callStackMethods:
printHello()
---
template: promise context
threadCommnads:
function displayUser(...
function printHello(...
function block500ms(...
setTimeout(printHello, 0)
const userFromServer = fetch('https://d.com/user/1')
block500ms()
displayUser(sagiv)
printHello()
displayUser:
printHello:
block500ms:
promiseObj:
timer:
timerStatus: true
taskClass:
microTaskClass:
xhr:
promiseThen:
consoleLogs:
global
sagiv
hello
callStackMethods:
---
template: questions
---
template: chapter
number: 4
title: Closure
subtitle: The Return Of The Function
---
layout: true
name: returning a function
mark1:
mark2:
mark3:
mark4:
mark5:
mark6:
mark7:
mark8:
callInnerFunction: // add2(5) throws the undefined error
memoFuncGenerator: hide
memoGeneratedFunc:hide
memoResult:hide
memoResultVal:
callstackGlobal:
callStackGeneratedFunc: hide
callStackfuncGenerator: hide
executionFuncGenerator: hide
executionGeneratedFunc: hide
executionContextSecond: hide
executionSecondAdd2: hide
executionSecondReturn: hide
memoAdd2: hide
executionContextThird: hide
executionThirdNum: hide
executionThirdReturn: hide
memoNum: hide
# Returning A Function
```
{{mark1}}function funcGenerator(){
{{mark2}} function add2(num){
{{mark3}} return num + 2;
{{mark4}} }
{{mark5}} return add2;
{{mark6}}}
{{mark7}}const generatedFunc = funcGenerator();
{{mark8}}// how do we call add2 ?
{{callInnerFunction}}
```
generatedFunc()
funcGenerator()
global()
function funcGenerator(){...}
generatedFunc = funcGenerator()
Thread
function add2(num){...}
return add2
result:
{{memoResultVal}}
---
template: returning a function
---
mark1:*
callstackGlobal: active-forced
executionFuncGenerator:
memoFuncGenerator:
---
mark7:*
callstackGlobal: active-forced
executionFuncGenerator:
memoFuncGenerator:
memoGeneratedFunc:
varDefenitionGeneratedFunc: undefined-var
---
mark2:*
callstackGlobal:
callStackfuncGenerator: active-forced
executionFuncGenerator:
memoFuncGenerator:
memoGeneratedFunc:
varDefenitionGeneratedFunc: undefined-var
executionContextSecond:
memoAdd2:
executionSecondAdd2:
---
mark5:*
callstackGlobal:
callStackfuncGenerator: active-forced
executionFuncGenerator:
memoFuncGenerator:
memoGeneratedFunc:
varDefenitionGeneratedFunc: undefined-var
executionContextSecond:
memoAdd2:
executionSecondAdd2:
executionSecondReturn:
---
mark6:*
callstackGlobal: active-forced
executionFuncGenerator:
memoFuncGenerator:
memoGeneratedFunc:
varDefenitionGeneratedFunc: function
executionContextSecond: garbage-context
memoAdd2:
executionSecondAdd2:
executionSecondReturn:
---
mark8:*
callstackGlobal: active-forced
executionFuncGenerator:
memoFuncGenerator:
memoGeneratedFunc:
varDefenitionGeneratedFunc: function
executionContextSecond: garbage-context
memoAdd2:
executionSecondAdd2:
executionSecondReturn:
---
callstackGlobal: active-forced
executionFuncGenerator:
memoFuncGenerator:
memoGeneratedFunc:
varDefenitionGeneratedFunc: function
executionContextSecond: garbage-context
memoAdd2:
executionSecondAdd2:
executionSecondReturn:
callInnerFunction: *const result = generatedFunc(5);
memoResult:
varDefenitionResult: undefined-var
---
mark2:*
callstackGlobal:
callStackGeneratedFunc: active-forced
executionFuncGenerator:
memoFuncGenerator:
memoGeneratedFunc:
varDefenitionGeneratedFunc: function
executionContextSecond: garbage-context
memoAdd2:
executionSecondAdd2:
executionSecondReturn:
callInnerFunction: *const result = generatedFunc(5);
memoResult:
varDefenitionResult: undefined-var
executionContextThird:
memoNum:
executionThirdNum:
callInnerFunction: const result = generatedFunc(5);
---
mark3:*
callstackGlobal:
callStackGeneratedFunc: active-forced
executionFuncGenerator:
memoFuncGenerator:
memoGeneratedFunc:
varDefenitionGeneratedFunc: function
executionContextSecond: garbage-context
memoAdd2:
executionSecondAdd2:
executionSecondReturn:
callInnerFunction: *const result = generatedFunc(5);
memoResult:
varDefenitionResult: undefined-var
executionContextThird:
memoNum:
executionThirdNum:
executionThirdReturn:
callInnerFunction: const result = generatedFunc(5);
---
mark4:*
callstackGlobal:
callStackGeneratedFunc: active-forced
executionFuncGenerator:
memoFuncGenerator:
memoGeneratedFunc:
varDefenitionGeneratedFunc: function
executionContextSecond: garbage-context
memoAdd2:
executionSecondAdd2:
executionSecondReturn:
callInnerFunction: *const result = generatedFunc(5);
memoResult:
varDefenitionResult: undefined-var
executionContextThird: garbage-context
memoNum:
executionThirdNum:
executionThirdReturn:
callInnerFunction: const result = generatedFunc(5);
---
callstackGlobal: active-forced
executionFuncGenerator:
memoFuncGenerator:
memoGeneratedFunc:
varDefenitionGeneratedFunc: function
executionContextSecond: garbage-context
memoAdd2:
executionSecondAdd2:
executionSecondReturn:
callInnerFunction: *const result = generatedFunc(5);
memoResult:
memoResultVal: 7
varDefenitionResult:
executionContextThird: garbage-context
memoNum:
executionThirdNum:
executionThirdReturn:
callInnerFunction: const result = generatedFunc(5); // 7
---
layout: true
name: lexical scope
# Lexical (static) Scope
Where you define your function determines What variables the function have access to When it gets called.
---
template: lexical scope
---
layout: true
name: lexical scope with code
template: lexical scope
mark1:
mark2:
mark3:
mark4:
mark5:
mark6:
mark7:
mark8:
executionContextShow:
callStackGlobal:
callStackInc: hide
callStackExternal: hide
executionGlobalExternal: hide
executionSecondCounter: hide
executionSecondinc: hide
executionSecondincInvoke: hide
executionThirdcounter: hide
executionContextSecond: hide
executionContextThird: hide
memoCounter: hide
counterResult: 0
memoExternal: hide
memoInc: hide
```
{{mark1}}function external() {
{{mark2}} let counter = 0;
{{mark3}} function inc() {
{{mark4}} counter++;
{{mark5}} }
{{mark6}} inc();
{{mark7}}}
{{mark8}}external();
```
inc()
external()
global()
external()
Thread
counter = 0
function inc(){...
inc()
counter:
{{counterResult}}
---
template: lexical scope with code
executionContextShow: hide
---
mark1:*
callStackGlobal: active-forced
memoExternal:
---
mark8:*
memoExternal:
executionGlobalExternal:
callStackExternal: active-forced
executionContextSecond:
---
mark2:*
memoExternal:
executionGlobalExternal:
callStackExternal: active-forced
executionContextSecond:
executionSecondCounter:
memoCounter:
---
mark3:*
memoExternal:
executionGlobalExternal:
callStackExternal: active-forced
executionContextSecond:
executionSecondCounter:
memoCounter:
executionSecondinc: hide
memoInc:
---
mark6:*
memoExternal:
executionGlobalExternal:
callStackExternal: active-forced
executionContextSecond:
executionSecondCounter:
memoCounter:
executionSecondinc: hide
memoInc:
executionSecondincInvoke:
---
mark3:*
memoExternal:
executionGlobalExternal:
callStackExternal:
executionContextSecond:
executionSecondCounter:
memoCounter:
executionSecondinc: hide
memoInc:
executionSecondincInvoke:
executionContextThird:
callStackInc: active-forced
---
mark4:*
memoExternal:
executionGlobalExternal:
callStackExternal:
executionContextSecond:
executionSecondCounter:
memoCounter:
executionSecondinc: hide
memoInc:
counterResult: 1
executionSecondincInvoke:
executionContextThird:
executionThirdcounter:
callStackInc: active-forced
---
mark5:*
memoExternal:
executionGlobalExternal:
callStackExternal: active-forced
executionContextSecond:
executionSecondCounter:
memoCounter:
executionSecondinc: hide
memoInc:
counterResult: 1
executionSecondincInvoke:
executionContextThird: garbage-context
executionThirdcounter:
---
mark7:*
memoExternal:
callStackGlobal: active-forced
executionGlobalExternal:
executionContextSecond: garbage-context
executionSecondCounter:
memoCounter:
executionSecondinc: hide
memoInc:
counterResult: 1
executionSecondincInvoke:
---
memoExternal:
callStackGlobal: active-forced
---
layout: false
# What if we want to call it externally?
```
function external() {
let counter = 0;
function inc() {
counter++;
}
}
// How can we do that without an error?
inc(); // counter = 1
inc(); // counter = 2
inc(); // counter = 3
```
### If we could do that, we had:
1. Persistent memory in between calls (data store)
2. Data Encapsulation
---
layout: true
name: closure
# The Magic Of Closure
---
layout: true
name: closure code
template: closure
mark1:
mark2:
mark3:
mark4:
mark5:
mark6:
mark7:
mark8:
mark9:
mark10:
callStackExternalInc: hide
callStackCounterGenerator: hide
executionGlobalCounterGenerator:
executionGlobalExternalIncExpression: hide
executionGlobalExternalIncFirst: hide
executionGlobalExternalIncSecond: hide
executionContextSecond: hide
executionSecondCounter: hide
executionSecondinc: hide
executionSecondincReturn: hide
memoCounter: hide
counterResult: 0
memoInc: hide
executionContextThird: hide
executionThirdCounter: hide
executionContextFourth: hide
executionFourthCounter: hide
memoExternalInc: hide
memoExternalIncVar: hide
closureBlock: hide
scope: hide
closure: hide
closureWrapper: //closure-wrapper
executionThirdlMissingVar: hide
executionFourthlMissingVar: hide
globalMissingVar: hide
```
{{mark1}}function counterGenerator() {
{{mark2}} let counter = 0;
{{mark3}} function inc() {
{{mark4}} counter++;
{{mark5}} }
{{mark6}} return inc;
{{mark7}}}
{{mark8}}const externalInc = counterGenerator(); // externalInc = inc
{{mark9}}externalInc();
{{mark10}}externalInc();
```
externalInc()
counterGenerator()
global()
counterGenerator(){...}
externalInc = counterGenerator()
externalInc()
externalInc()
Thread
counter = 0
function inc(){...
return inc
counter:
{{counterResult}}
[[scope]]
↳
{
counter: {{counterResult}}
}
⚠
---
template: closure code
executionGlobalCounterGenerator: hide
memoCounterGenerator: hide
---
mark1:*
callStackGlobal: active-forced
---
mark8:*
callStackGlobal: active-forced
executionGlobalExternalIncExpression:
memoExternalInc:
memoExternalIncVar: undefined-var
---
mark2:*
callStackCounterGenerator: active-forced
executionGlobalExternalIncExpression:
memoExternalInc:
memoExternalIncVar: undefined-var
executionContextSecond:
executionSecondCounter:
memoCounter:
---
mark3:*
callStackCounterGenerator: active-forced
executionGlobalExternalIncExpression:
memoExternalInc:
memoExternalIncVar: undefined-var
executionContextSecond:
executionSecondCounter:
memoCounter:
executionSecondinc:
memoInc:
---
mark6:*
callStackCounterGenerator: active-forced
executionGlobalExternalIncExpression:
memoExternalInc:
memoExternalIncVar: undefined-var
executionContextSecond:
executionSecondCounter:
memoCounter:
memoInc:
executionSecondinc:
executionSecondincReturn:
---
mark7:*
callStackGlobal: active-forced
executionGlobalExternalIncExpression:
memoExternalInc:
memoExternalIncVar: function
executionContextSecond:
executionSecondCounter:
memoCounter:
memoInc:
executionSecondinc:
executionSecondincReturn:
executionContextSecond: garbage-context
---
mark9:*
callStackGlobal: active-forced
executionGlobalExternalIncExpression:
memoExternalInc:
memoExternalIncVar: function
executionContextSecond:
executionSecondCounter:
memoCounter:
memoInc:
executionSecondinc:
executionSecondincReturn:
executionContextSecond: garbage-context
---
mark3:*
callStackExternalInc: active-forced
executionGlobalExternalIncExpression:
memoExternalInc:
memoExternalIncVar: function
executionContextSecond:
executionSecondCounter:
memoCounter:
memoInc:
executionSecondinc:
executionSecondincReturn:
executionContextSecond: garbage-context
executionContextThird:
---
mark4:*
callStackExternalInc: active-forced
executionGlobalExternalIncExpression:
memoExternalInc:
memoExternalIncVar: function
executionContextSecond:
executionSecondCounter:
memoCounter:
memoInc:
executionSecondinc:
executionSecondincReturn:
executionContextSecond: garbage-context
executionContextThird:
executionThirdCounter:
---
mark4:*
callStackExternalInc: active-forced
executionGlobalExternalIncExpression:
memoExternalInc:
memoExternalIncVar: function
executionContextSecond:
executionSecondCounter:
memoCounter:
memoInc:
executionSecondinc:
executionSecondincReturn:
executionContextSecond: garbage-context
executionContextThird:
executionThirdCounter:
executionThirdlMissingVar:
---
mark4:*
callStackExternalInc: active-forced
executionGlobalExternalIncExpression:
memoExternalInc:
memoExternalIncVar: function
executionContextSecond:
executionSecondCounter:
memoCounter:
memoInc:
executionSecondinc:
executionSecondincReturn:
executionContextSecond: garbage-context
executionContextThird:
executionThirdCounter:
executionThirdlMissingVar:
globalMissingVar:
---
template: lexical scope
--
### Don't forget where we defined the function
```
function counterGenerator() {
let counter = 0;
* function inc() {
* counter++;
* }
return inc;
}
```
---
mark4:*
callStackExternalInc: active-forced
executionGlobalExternalIncExpression:
memoExternalInc:
memoExternalIncVar: function
executionContextSecond:
executionSecondCounter:
memoCounter:
memoInc:
executionSecondinc:
executionSecondincReturn:
executionContextSecond: garbage-context
executionContextThird:
executionThirdCounter:
closureBlock:
closure:
closureWrapper: closure-wrapper
---
mark4:*
callStackExternalInc: active-forced
executionGlobalExternalIncExpression:
memoExternalInc:
memoExternalIncVar: function
executionContextSecond:
executionSecondCounter:
memoCounter:
memoInc:
executionSecondinc:
executionSecondincReturn:
executionContextSecond: garbage-context
executionContextThird:
executionThirdCounter:
closureBlock:
closure:
closureWrapper: closure-wrapper
scope:
---
mark4:*
callStackExternalInc: active-forced
executionGlobalExternalIncExpression:
memoExternalInc:
memoExternalIncVar: function
executionContextSecond:
executionSecondCounter:
memoCounter:
memoInc:
executionSecondinc:
executionSecondincReturn:
executionContextSecond: garbage-context
executionContextThird:
executionThirdCounter:
closureBlock:
closure:
closureWrapper: closure-wrapper
scope:
counterResult: 1
---
mark5:*
callStackGlobal: active-forced
executionGlobalExternalIncExpression:
memoExternalInc:
memoExternalIncVar: function
executionContextSecond:
executionSecondCounter:
memoCounter:
memoInc:
executionSecondinc:
executionSecondincReturn:
executionContextSecond: garbage-context
executionContextThird: garbage-context
executionThirdCounter:
closureBlock:
closure:
closureWrapper: closure-wrapper
scope:
counterResult: 1
---
mark10:*
callStackGlobal: active-forced
executionGlobalExternalIncExpression:
memoExternalInc:
memoExternalIncVar: function
executionContextSecond:
executionSecondCounter:
memoCounter:
memoInc:
executionSecondinc:
executionSecondincReturn:
executionContextSecond: garbage-context
executionContextThird: garbage-context
executionThirdCounter:
closureBlock:
closure:
closureWrapper: closure-wrapper
scope:
counterResult: 1
---
mark3:*
callStackExternalInc: active-forced
executionGlobalExternalIncExpression:
memoExternalInc:
memoExternalIncVar: function
executionContextSecond:
executionSecondCounter:
memoCounter:
memoInc:
executionSecondinc:
executionSecondincReturn:
executionContextSecond: garbage-context
executionContextThird: garbage-context
executionThirdCounter:
closureBlock:
closure:
closureWrapper: closure-wrapper
scope:
counterResult: 1
executionContextFourth:
---
mark4:*
callStackExternalInc: active-forced
executionGlobalExternalIncExpression:
memoExternalInc:
memoExternalIncVar: function
executionContextSecond:
executionSecondCounter:
memoCounter:
memoInc:
executionSecondinc:
executionSecondincReturn:
executionContextSecond: garbage-context
executionContextThird: garbage-context
executionThirdCounter:
closureBlock:
closure:
closureWrapper: closure-wrapper
scope:
counterResult: 1
executionContextFourth:
executionFourthCounter:
executionFourthlMissingVar:
--
counterResult: 2
--
mark4:
mark5:*
executionContextFourth: garbage-context
--
mark4:
mark5:
callStackGlobal: active-forced
callStackExternalInc: hide
---
layout: false
# What can we do with persistent data?
For example we can memoize our functions:
Turn this
```
function square(num){
return num * num;
}
const result = square(5);
const result2 = square(5); // a second calculation
```
Into this
```
function memoSquareGenerator(){
let cache = {};
function square(num){
if(cache[num]){
return cache[num];
} else {
cache[num] = num * num;
return cache[num];
}
}
return square;
}
const memoSquare = memoSquareGenerator();
const result = memoSquare(5);
const result2 = memoSquare(5); // no extra calculations
```
---
Or even better, we can generalize it:
```
function memoize(fn) {
var cache = {};
return function(...args) {
const key = JSON.stringify(args);
const result = cache[key] = cache[key] || fn(...args);
return result
}
}
const double = memoize(n => n * 2);
const square = memoize(n => n * n);
const result = double(5); // 10
const result2 = square(5); // 25
```
--
**Note - ** This pattern is called currying (after Haskell Brooks Curry)
Currying is the process of breaking down a function into a series of functions that each take a single argument.
---
template: questions
---
template: chapter
number: 5
title: Event loop, again?!
subtitle: What about rendering???
---
class: center, middle, fade
layout: true
name: raf
blockingWhile: hide
noneBlockingWhile: hide
# {{title}}
btn.addEventListener('click', evt => {
while(true);
});
function loop() {
setTimeout(loop, 0);
}
loop();
---
template: raf
title: This is the event loop
imageName: simple_task.gif
Jake Archibald - The Secret of the Loop
---
title: These are the render steps
imageName: render steps.gif
--
title: Blocking Tasks
blockingWhile:
---
title: Blocking Tasks
imageName: while loop normal task.gif
--
title: None Blocking Tasks
noneBlockingWhile:
---
title: None Blocking Tasks
imageName: while loop setTimeout.gif
---
title: Request Animation Frame (rAF)
imageName: with_rAF.gif
---
layout: true
template: false
name: move a box
title:
demoParams:
class: huge-font
### {{title}}
---
template: move a box
title: Move a box
demoClass: transparent
```
// The move function
function move1px(el) {
let left = 0;
return function () {
// infinite looping logic - if off screen start over
if (document.documentElement.clientWidth < left) {
left = 0;
} else {
left++;
}
// move left by 1 px
el.style.left = left + 'px';
}
}
```
--
template: move a box
title: raF Solution
demoClass:
```
// using rAF
const moveBox1 = move1px(box1);
function callback() {
moveBox1();
requestAnimationFrame(callback);
}
callback();
```
--
template: move a box
title: setInterval Solution
demoClass:
demoParams: box2
```
// using a task (setInterval)
const moveBox2 = move1px(box2);
setInterval(moveBox2, 0);
```
--
template: move a box
title: setInterval hack Solution
demoParams: box2&box3
```
// using a task with a hack
const moveBox3 = move1px(box3);
setInterval(moveBox2, 1000 / 60);
```
---
template: raf
title: rAF callback is invoked on each frame
imageName: with_rAF.gif
---
layout: true
name: que process
title:
imageName:
imageClass:
class: center, middle, fade
# 3 Different Que types
#### {{title}}
---
template: que process
imageClass: transparent
title: Not all ques are processed the same way
imageName: loop priority tasks.gif
---
template: que process
title: Task Que - Run 1 item at a time
imageName: loop priority tasks.gif
---
template: que process
title: rAF callbacks - run to completion (except new items)
imageName: loop priority rAF.gif
---
template: que process
title: Micro Tasks - run to completion (with new items)
imageName: loop priority micro tasks _promises.gif
---
template: questions
---
layout: false
class: fade
# Useful Links
developer.mozilla.org/en-US/docs/Web/API
Jake Archibald - The Secret of the Loop
Philip Roberts: What the heck is the event loop anyway?
Will Sentance - JavaScript: The Hard Parts
---
class: middle, home, fade
# Async JavaScript
## FROM SCRATCH
#### Part #2
To be continued...