Gerard Sans | Axiom 🇬🇧 PRO
Founder of Axiom Masterclass, professional trainings // Forging skills for the new era of AI. GDE in AI, Cloud & Angular. Building London's tech & art nexus @nextai_london. Speaker | MC | Trainer.
SANS
GERARD
Spoken at 164 events in 37 countries
DOM events
HTTP Requests
setTimeout setInterval
Promises async/await
const log = console.log;
const macro = v => setTimeout(() => log(v));
const micro = v => Promise.resolve().then(() => log(v));
log(1);
macro(2);
micro(3);
log(4);
a) 1 2 3 4
b) 1 4 2 3
c) 1 4 3 2setTimeout(() => log(1));
setTimeout(() => log(2), 0);
log(3)
// a) 1 2 3
// b) 3 2 1
// c) 3 1 2YAY!
setTimeout(() => log(1), 1000);
setTimeout(() => log(2), 2000);
setTimeout(() => log(3), 3000);
// a) 1 2 3 (wait aprox. 1s)
// b) 1 2 3 (wait aprox. 3s)
// c) 1 2 3 (wait aprox. 6s)
Time
50ms
task 1
task 2
task 3
task < delay
Time
50ms
task 1
task 2
task 3
task > delay
task 1
task 2
task 3
Reality
Ideal
audit auditTime buffer bufferCount bufferTime bufferToggle bufferWhen catchError combineLatestAll combineLatestWith concatAll concatMap concatMapTo concatWith connect count debounce debounceTime defaultIfEmpty delay delayWhen dematerialize distinct distinctUntilChanged distinctUntilKeyChanged elementAt endWith every exhaustAll exhaustMap expand filter finalize find findIndex first groupBy ignoreElements isEmpty last map mapTo materialize max merge mergeAll mergeMap mergeMapTo mergeScan mergeWith min observeOn onErrorResumeNext pairwise raceWith reduce repeat repeatWhen retry retryWhen sample sampleTime scan sequenceEqual share shareReplay single skip skipLast skipUntil skipWhile startWith subscribeOn switchAll switchMap switchMapTo switchScan take takeLast takeUntil takeWhile tap throttle throttleTime throwIfEmpty timeInterval timeout timeoutWith timestamp toArray window windowCount windowTime windowToggle windowWhen withLatestFrom zipAll zipWith
of(1, 2, 3)
.subscribe(
v => console.log(v)
);1
2
3
of(1).subscribe(v => l(v));
l(2);
// 1 2
import { asyncScheduler } from 'rxjs';
of(1, asyncScheduler).subscribe(v => l(v));
l(2);
// 2 1
import { queueScheduler } from 'rxjs';
queueScheduler.schedule(() => log(1));
log(2);
queueScheduler.schedule(() => log(3));
// 1 2 3
queueScheduler.schedule(() => {
queueScheduler.schedule(() => log(1));
log(2);
queueScheduler.schedule(() => log(3));
});
// 2 1 3import { asapScheduler } from 'rxjs';
import { queueScheduler } from 'rxjs';
setTimeout(() => log(1));
asapScheduler.schedule(() => log(2));
queueScheduler.schedule(() => log(3));
// 3 2 1import { asyncScheduler } from 'rxjs';
import { queueScheduler } from 'rxjs';
asapScheduler.schedule(() => log(2));
asyncScheduler.schedule(() => log(1));
queueScheduler.schedule(() => log(3));
// 3 2 1DURATION
0%
100%
KEYFRAMES
60 FPS
Time
16.66ms
16.66ms
16.66ms
1000/60ms
paint
frame
paint
frame
paint
frame
60 FPS
Time
16.66ms
16.66ms
16.66ms
paint
frame
paint
frame
paint
frame
const token = setInterval(paintFrame, 1000/60);
const paintFrame = () => {
// animation code
}
setTimeout(() => clearInterval(token), 40);
60 FPS
Time
16.66ms
16.66ms
16.66ms
1000/60ms
paint
frame
paint
frame
paint
frame
let token = requestAnimationFrame(paintFrame);
const paintFrame = (timestamp) => {
// animation code
token = requestAnimationFrame(paintFrame)
}
setTimeout(() => cancelAnimationFrame(token), 40);let state = { angle: 0 };
const div = document.querySelector('.circle');
animationFrames().pipe(
tap(render)
).subscribe();
function render({ timestamp, elapsed }) {
let { angle } = state;
state = { angle: ++angle % 360 };
(div as HTMLDivElement).style.transform = `rotate(${angle}deg)`;
}| # | Type | Execution | Primitives |
|---|---|---|---|
| 1 | queueScheduler | Sync | scheduler.schedule(task, delay) scheduler.flush() |
| 2 | asapScheduler | Async (micro) | Promise.resolve().then(() => task) |
| 3 | animationFrameScheduler | Async (rAf) | id = requestAnimationFrame(task) cancelAnimationFrame(id) |
| 4 | asyncScheduler | Async (macro) | id = setInterval(task, delay) clearInterval(id) |
Next tick - Next tick - Next tick - Next tick - Next tick - Next tick
By Gerard Sans | Axiom 🇬🇧
Did you ever notice your laptop going cray-cray after you open a Web Page? Usual suspects are animations, heavy duty framework bootstrap, using setTimeout/setInterval without a Developer license?!? There's certainly a mysterious side of JavaScript that deals with concurrency, asynchronous processing and high performance that can go terribly wrong. In this talk we are going to put the event loop under the microscope and really look at what is happening behind the scenes. Will we cover macro and microtasks? Yep. We are going to roll our sleeves up and use RxJS to deal with concurrency. Instead of creating microtasks we will use RxJS Schedulers elegant abstraction to improve performance without losing control. Let's avoid more CPUs cycles going to waste today!
Founder of Axiom Masterclass, professional trainings // Forging skills for the new era of AI. GDE in AI, Cloud & Angular. Building London's tech & art nexus @nextai_london. Speaker | MC | Trainer.