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 2
setTimeout(() => log(1));
setTimeout(() => log(2), 0);
log(3)
// a) 1 2 3
// b) 3 2 1
// c) 3 1 2
YAY!
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 3
import { asapScheduler } from 'rxjs';
import { queueScheduler } from 'rxjs';
setTimeout(() => log(1));
asapScheduler.schedule(() => log(2));
queueScheduler.schedule(() => log(3));
// 3 2 1
import { asyncScheduler } from 'rxjs';
import { queueScheduler } from 'rxjs';
asapScheduler.schedule(() => log(2));
asyncScheduler.schedule(() => log(1));
queueScheduler.schedule(() => log(3));
// 3 2 1
DURATION
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