SlideShare a Scribd company logo
Don't block the event loop!
JavaScript Async for Effortless UX
Jaeseok Kang

(kang89kr@gmail.com)
Jaeseok Kang
JSConf Korea 2019JS
Jaeseok Kang
JSConf Korea 2019JSConf Korea 2019
Jaeseok Kang
I'm going to talk about..!
Cause SolutionProblem
Cause Solution
• "Page freeze.."

• "Responding to
user input too
slow.."

• "Glitchy
animations.."

• ...
Problem
• run-to-completion

• javascript engine

• call stack

• event loop

• task queue

• ...
• worker

• scheduling

• ...
This is an exploration
for a better solution,
not a clear solution.
⚠
User Experience
Users' feelings about using a product, system or service
https://userexperiencerocks.wordpress.com/2015/08/20/then-my-kiddo-asked-whats-the-difference-between-ux-ui/
• "Page freeze.."

• "Responding to user input too slow.."

• "Glitchy animations.."
Why do they happen?
Something may be slowing things
down and blocking others. #
Run-to-completion $
Run-to-completion
• Each message is processed completely before any other
message is processed.
let running = true
setTimeout(() => {
console.log('Will it be print?')
}, 500)
while(true) {
if (!running) {
break
}
console.log('Running...', Date.now())
}
let running = true
setTimeout(() => {
console.log('Will it be print?')
}, 500)
while(true) {
if (!running) {
break
}
console.log('Running...', Date.now())
}
1.set running to true
let running = true
setTimeout(() => {
console.log('Will it be print?')
}, 500)
while(true) {
if (!running) {
break
}
console.log('Running...', Date.now())
}
1.set running to true
2.run setTimeout function
let running = true
setTimeout(() => {
console.log('Will it be print?')
}, 500)
while(true) {
if (!running) {
break
}
console.log('Running...', Date.now())
}
1.set running to true
2.run setTimeout function
3.start while loop block
let running = true
setTimeout(() => {
console.log('Will it be print?')
}, 500)
while(true) {
if (!running) {
break
}
console.log('Running...', Date.now())
}
1.set running to true
2.run setTimeout function
3.start while loop block
4.check if running have changed
let running = true
setTimeout(() => {
console.log('Will it be print?')
}, 500)
while(true) {
if (!running) {
break
}
console.log('Running...', Date.now())
}
1.set running to true
2.run setTimeout function
3.start while loop block
4.check if running have changed
5.print log 'Running...'
let running = true
setTimeout(() => {
console.log('Will it be print?')
}, 500)
while(true) {
if (!running) {
break
}
console.log('Running...', Date.now())
}
1.set running to true
2.run setTimeout function
3.start while loop block
4.check if running have changed
5.print log 'Running...'
6.500ms later... running still true
let running = true
setTimeout(() => {
console.log('Will it be print?')
}, 500)
while(true) {
if (!running) {
break
}
console.log('Running...', Date.now())
}
1.set running to true
2.run setTimeout function
3.start while loop block
4.check if running have changed
5.print log 'Running...'
6.500ms later... running still true
7.running is true as ever..
let running = true
setTimeout(() => {
console.log('Will it be print?')
}, 500)
while(true) {
if (!running) {
break
}
console.log('Running...', Date.now())
}
1.set running to true
2.run setTimeout function
3.start while loop block
4.check if running have changed
5.print log 'Running...'
6.500ms later... running still true
7.running is true as ever..
8.and ever...
let running = true
setTimeout(() => {
console.log('Will it be print?')
}, 500)
while(true) {
if (!running) {
break
}
console.log('Running...', Date.now())
}
1.set running to true
2.run setTimeout function
3.start while loop block
4.check if running have changed
5.print log 'Running...'
6.500ms later... running still true
7.running is true as ever..
8.and ever...
9. ...forever....
let running = true
setTimeout(() => {
console.log('Will it be print?')
}, 500)
while(true) {
if (!running) {
break
}
console.log('Running...', Date.now())
}
JavaScript Async for Effortless UX
Call stack %
function hello() {
console.log('hello')
}
function helloJsConf() {
hello()
console.log('JSConfKorea')
}
helloJsConf()
function hello() {
console.log('hello')
}
function helloJsConf() {
hello()
console.log('JSConfKorea')
}
helloJsConf()
main()
function hello() {
console.log('hello')
}
function helloJsConf() {
hello()
console.log('JSConfKorea')
}
helloJsConf()
helloJsConf()
main()
function hello() {
console.log('hello')
}
function helloJsConf() {
hello()
console.log('JSConfKorea')
}
helloJsConf()
helloJsConf()
hello()
main()
function hello() {
console.log('hello')
}
function helloJsConf() {
hello()
console.log('JSConfKorea')
}
helloJsConf()
helloJsConf()
hello()
main()
console.log("hello")
function hello() {
console.log('hello')
}
function helloJsConf() {
hello()
console.log('JSConfKorea')
}
helloJsConf()
helloJsConf()
hello()
main()
function hello() {
console.log('hello')
}
function helloJsConf() {
hello()
console.log('JSConfKorea')
}
helloJsConf()
helloJsConf()
main()
function hello() {
console.log('hello')
}
function helloJsConf() {
hello()
console.log('JSConfKorea')
}
helloJsConf()
helloJsConf()
main()
console.log("jsConfKorea")
function hello() {
console.log('hello')
}
function helloJsConf() {
hello()
console.log('JSConfKorea')
}
helloJsConf()
helloJsConf()
main()
function hello() {
console.log('hello')
}
function helloJsConf() {
hello()
console.log('JSConfKorea')
}
helloJsConf()
main()
function hello() {
console.log('hello')
}
function helloJsConf() {
hello()
console.log('JSConfKorea')
}
helloJsConf()
Let’s say we have some
expensive task &
function someExpensive() {
...
}
function hello() {
someExpensive()
console.log('hello')
}
function helloJsConf() {
hello()
console.log('JSConfKorea')
}
helloJsConf()
main()
function someExpensive() {
...
}
function hello() {
someExpensive()
console.log('hello')
}
function helloJsConf() {
hello()
console.log('JSConfKorea')
}
helloJsConf()
helloJsConf()
main()
function someExpensive() {
...
}
function hello() {
someExpensive()
console.log('hello')
}
function helloJsConf() {
hello()
console.log('JSConfKorea')
}
helloJsConf()
helloJsConf()
hello()
main()
function someExpensive() {
...
}
function hello() {
someExpensive()
console.log('hello')
}
function helloJsConf() {
hello()
console.log('JSConfKorea')
}
helloJsConf()
helloJsConf()
hello()
main()
function someExpensive() {
...
}
function hello() {
someExpensive()
console.log('hello')
}
function helloJsConf() {
hello()
console.log('JSConfKorea')
}
helloJsConf()
someExpensive()
helloJsConf()
hello()
main()
function someExpensive() {
...
}
function hello() {
someExpensive()
console.log('hello')
}
function helloJsConf() {
hello()
console.log('JSConfKorea')
}
helloJsConf()
someExpensive()
'
How to handle concurrency
in browser? ⚙
Web APIs ⏱
•dom events

•XMLHttpRequest

•setTimeout

•Promise

•requestAnimationFrame

•...
Event loop *
Event loop *
Event loop
while(queue.waitForMessage()) {
queue.processNextMessage()
}
https://developer.mozilla.org/ko/docs/Web/JavaScript/EventLoop#Event_loop
Event loop
• Event loop manages what task
is to be pushed in the Callstack.
Event loop
1. While there are tasks:

• execute the oldest task.

2. Sleep until a task appears, then go to 1.
setTimeout(() => {
console.log('hello')
})
Promise.resolve().then(() => {
console.log('JSConfKorea')
})
Call Stack
Tasks
Event Loop
setTimeout(() => {
console.log('hello')
})
Promise.resolve().then(() => {
console.log('JSConfKorea')
})setTimeout()
Call Stack
Tasks
Event Loop
setTimeout(() => {
console.log('hello')
})
Promise.resolve().then(() => {
console.log('JSConfKorea')
})
Call Stack
Tasks
Event Loop
hello
Task
setTimeout(() => {
console.log('hello')
})
Promise.resolve().then(() => {
console.log('JSConfKorea')
})Promise.resolve.then()
Call Stack
Tasks
Event Loop
hello
Task
Microtasks
setTimeout(() => {
console.log('hello')
})
Promise.resolve().then(() => {
console.log('JSConfKorea')
})Promise.resolve.then()
Call Stack
Tasks
Event Loop
hello
Task
Microtasks
setTimeout(() => {
console.log('hello')
})
Promise.resolve().then(() => {
console.log('JSConfKorea')
})
Call Stack
Tasks
Event Loop
hello
Task
jsConfKorea
Micro Task
Microtasks
setTimeout(() => {
console.log('hello')
})
Promise.resolve().then(() => {
console.log('JSConfKorea')
})
Call Stack
Tasks
Event Loop
hello
Task
jsConfKorea
Micro Task
?
Task & Microtask
•Task
Task that should execute sequentially in browser

Source : setTimeout, running scripts, UI events..

•Microtask
Async task that should happen after the currently
executing script

Microtask queue has a higher priority than the task
queue.

Source : Promise, MutationObserver, process.nextTick
Event loop
1. While there are tasks:

• execute the oldest task.

2. Sleep until a task appears, then go to 1.
Event loop - Detail
1. If the microtask queue is not empty,
execute all microtasks
2. While there are tasks:

• execute the oldest task.

3. Sleep until a task appears, then go to 1.
Call Stack
Tasks
Event Loop
hello
Task
jsConfKorea
Micro Task
Microtasks
setTimeout(() => {
console.log('hello')
})
Promise.resolve().then(() => {
console.log('JSConfKorea')
})
Call Stack
Tasks
Event Loop
hello
Task
jsConfKorea
Micro Task
Microtasks
setTimeout(() => {
console.log('hello')
})
Promise.resolve().then(() => {
console.log('JSConfKorea')
})
Call Stack
Tasks
Event Loop
hello
Task
Microtasks
setTimeout(() => {
console.log('hello')
})
Promise.resolve().then(() => {
console.log('JSConfKorea')
})
Call Stack
Tasks
Event Loop
hello
Task
Microtasks
setTimeout(() => {
console.log('hello')
})
Promise.resolve().then(() => {
console.log('JSConfKorea')
})
Call Stack
Tasks
Event Loop
Microtasks
setTimeout(() => {
console.log('hello')
})
Promise.resolve().then(() => {
console.log('JSConfKorea')
})
So...
Can asynchronous JavaScript
solve all the problems?
So...
Can asynchronous JavaScript
solve all the problems?
+
function someExpensive() {
...
}
setTimeout(() => {
console.log('hello JSConfKorea')
})
Promise.resolve().then(() => {
someExpensive()
})
Call Stack
Event Loop
Tasks
Microtasks
function someExpensive() {
...
}
setTimeout(() => {
console.log('hello JSConfKorea')
})
Promise.resolve().then(() => {
someExpensive()
})
setTimeout()
Call Stack
Event Loop
Tasks
Microtasks
function someExpensive() {
...
}
setTimeout(() => {
console.log('hello JSConfKorea')
})
Promise.resolve().then(() => {
someExpensive()
})
Call Stack
Event Loop hello JSConfKorea
Task
Tasks
Microtasks
function someExpensive() {
...
}
setTimeout(() => {
console.log('hello JSConfKorea')
})
Promise.resolve().then(() => {
someExpensive()
})
Promise.resolve.then()
Call Stack
Event Loop hello JSConfKorea
Task
Tasks
Microtasks
function someExpensive() {
...
}
setTimeout(() => {
console.log('hello JSConfKorea')
})
Promise.resolve().then(() => {
someExpensive()
})
Call Stack
Event Loop hello JSConfKorea
Task
someExpensive
Micro Task
Tasks
Microtasks
function someExpensive() {
...
}
setTimeout(() => {
console.log('hello JSConfKorea')
})
Promise.resolve().then(() => {
someExpensive()
})
Call Stack
Event Loop hello JSConfKorea
Task
someExpensive
Micro Task
Tasks
Microtasks
function someExpensive() {
...
}
setTimeout(() => {
console.log('hello JSConfKorea')
})
Promise.resolve().then(() => {
someExpensive()
})
Call Stack
Event Loop hello JSConfKorea
Task
someExpensive
Micro Task
'
Tasks
Microtasks
• Task is always executed sequentially by event loop.

Other task cannot be performed when any task is running.

• Microtask queue has a higher priority than the task queue.

So, UI-related events cannot be executed again until all
microtasks accumulated in the queue are cleared.

• What if long running stacked tasks or microtasks block event
that is directly connected to UI such as rendering, click, input?

janky UI/UX occurs... ,
How to handle this blocking?
'
Demo
https://github.com/jaeseokk/ui-block-demo
inputEl.addEventListener('input', (e) => {
const textLength = e.target.value.length
let result = ''
for (let i; i < getSquareCounts(textLength); i++) {
result += makeSquareWithRandomColorHtml()
}
containerEl.innerHTML = result
})
inputEl.addEventListener('input', (e) => {
const textLength = e.target.value.length
let result = ''
for (let i; i < getSquareCounts(textLength); i++) {
result += makeSquareWithRandomColorHtml()
}
containerEl.innerHTML = result
})
Too many iterations
inputEl.addEventListener('input', (e) => {
const textLength = e.target.value.length
let result = ''
for (let i; i < getSquareCounts(textLength); i++) {
result += makeSquareWithRandomColorHtml()
}
containerEl.innerHTML = result
})
Too many iterations
Costly DOM changes
JavaScript Async for Effortless UX
JavaScript Async for Effortless UX
•With another thread...? 

- Web Workers

•Split some expensive task into small tasks...? 

- Scheduling
Web Workers
•Web Workers makes it possible to
run a script operation in a
background thread separate from the
main execution thread of a web
application.
https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
Main Thread Worker Thread
2. result = runLongRunningTask()
1. postMessage()
3. postMessage(result)
4. doSomethingWith(result)
self.addEventListener('message', e => {
const result = runLongRunningTask()
postMessage(result)
})
// spawn a worker
const worker = new Worker('worker.js')
// send messages to a worker for request run long-runnging-task
worker.postMessage(message)
// handle a `message` event from a worker
worker.onmessage = e => {
doSomethingWith(e)
}
worker.js
main.js
JavaScript Async for Effortless UX
JavaScript Async for Effortless UX
Limitations
• Data is sent between workers and the main
thread via a system of messages.

• Worker cannot access directly the DOM,
context.
Scheduling
• Slice your heavy task in light sub-tasks and run
them asynchronously.
TaskLong Running Task TaskTask Task
Task TaskTask Task
function* chunkGenerator (textLength) {
let result = ''
for (let i = 0; i < getSquareCounts(textLength) / CHUNK_UNIT; i++) {
for (let j = 0; j < CHUNK_UNIT; j++) {
result = makeSquareWithRandomColorHtml()
}
yield
}
containerEl.innerHTML = result
}
inputEl.addEventListener('input', (e) => {
const textLength = e.target.value.length
runChunks(chunkGenerator(textLength))
})
inputEl.addEventListener('input', (e) => {
const textLength = e.target.value.length
let result = ''
for (let i = 0; i < getSquareCounts(textLength); i++) {
result += makeSquareWithRandomColorHtml()
}
containerEl.innerHTML = result
})
AS-IS
TO-BE
https://github.com/jaeseokk/chunk-scheduler
JavaScript Async for Effortless UX
JavaScript Async for Effortless UX
inputEl.addEventListener('input', (e) => {
const textLength = e.target.value.length
if (isRunning()) {
cancel()
}
runChunks(chunkGenerator(textLength))
})
JavaScript Async for Effortless UX
JavaScript Async for Effortless UX
Recap
• If long-running-tasks or microtasks block rendering, click, and
text input, a janky UI that harms user experience can be
delivered can occur.
• This is due to the structure of the JavaScript engine, event-
loop, etc. and needs to understand and handle properly.
• To handle this, Delegate long-running-tasks to other threads
using Web Worker,
• Or, split the long-running-task properly so that other important
UI events do not block.
Thank you -

More Related Content

PDF
Intro to Sail.js
PDF
What is nodejs
PPTX
How NOT to write in Node.js
KEY
Node.js 0.8 features
PDF
soft-shake.ch - Hands on Node.js
KEY
Building a real life application in node js
PPTX
Bucks County Tech Meetup: node.js introduction
PDF
Developing Async Sense
Intro to Sail.js
What is nodejs
How NOT to write in Node.js
Node.js 0.8 features
soft-shake.ch - Hands on Node.js
Building a real life application in node js
Bucks County Tech Meetup: node.js introduction
Developing Async Sense

What's hot (20)

PDF
Node azure
PDF
Arquitetando seu app Android com Jetpack
PDF
Introduction to Nodejs
PDF
Future Decoded - Node.js per sviluppatori .NET
KEY
Introduction to node.js
KEY
Writing robust Node.js applications
PDF
Understanding Asynchronous JavaScript
PDF
Matthew Eernisse, NodeJs, .toster {webdev}
PPTX
introduction to node.js
PPTX
The State of JavaScript (2015)
KEY
node.js: Javascript's in your backend
PDF
Building servers with Node.js
PPTX
Vue.js + Django - configuración para desarrollo con webpack y HMR
PPTX
Scalable Web Apps
PDF
Future of Web Apps: Google Gears
PPTX
Angular 1 + es6
PDF
Server Side JavaScript - You ain't seen nothing yet
KEY
A million connections and beyond - Node.js at scale
PDF
Aplicações assíncronas no Android com
Coroutines & Jetpack
PDF
Boom! Promises/A+ Was Born
Node azure
Arquitetando seu app Android com Jetpack
Introduction to Nodejs
Future Decoded - Node.js per sviluppatori .NET
Introduction to node.js
Writing robust Node.js applications
Understanding Asynchronous JavaScript
Matthew Eernisse, NodeJs, .toster {webdev}
introduction to node.js
The State of JavaScript (2015)
node.js: Javascript's in your backend
Building servers with Node.js
Vue.js + Django - configuración para desarrollo con webpack y HMR
Scalable Web Apps
Future of Web Apps: Google Gears
Angular 1 + es6
Server Side JavaScript - You ain't seen nothing yet
A million connections and beyond - Node.js at scale
Aplicações assíncronas no Android com
Coroutines & Jetpack
Boom! Promises/A+ Was Born
Ad

Similar to JavaScript Async for Effortless UX (20)

PPTX
JavaScript Multithread or Single Thread.pptx
PPTX
Events for JavaScript event loop track.pptx
PDF
Promise: async programming hero
PPTX
The JavaScript Event Loop - Concurrency in the Language of the Web
PPT
JavaScript Event Loop
PPTX
JS Event Loop
PDF
Douglas Crockford: Serversideness
PDF
Javascript internals
PDF
Intro to Asynchronous Javascript
PPTX
All you need to know about the JavaScript event loop
PPTX
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
PDF
Event driven javascript
PDF
Event driven javascript
PPTX
Node js for backend server development.
PDF
Event Driven Javascript
PDF
The evolution of asynchronous JavaScript
KEY
Playing With Fire - An Introduction to Node.js
PPTX
Javascript why what and how
PPTX
[DevDay2018] How does JavaScript actually work? - By: Vi Nguyen, Senior Softw...
PDF
"Leveraging the Event Loop for Blazing-Fast Applications!", Michael Di Prisco
JavaScript Multithread or Single Thread.pptx
Events for JavaScript event loop track.pptx
Promise: async programming hero
The JavaScript Event Loop - Concurrency in the Language of the Web
JavaScript Event Loop
JS Event Loop
Douglas Crockford: Serversideness
Javascript internals
Intro to Asynchronous Javascript
All you need to know about the JavaScript event loop
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Event driven javascript
Event driven javascript
Node js for backend server development.
Event Driven Javascript
The evolution of asynchronous JavaScript
Playing With Fire - An Introduction to Node.js
Javascript why what and how
[DevDay2018] How does JavaScript actually work? - By: Vi Nguyen, Senior Softw...
"Leveraging the Event Loop for Blazing-Fast Applications!", Michael Di Prisco
Ad

Recently uploaded (20)

PPTX
OOP with Java - Java Introduction (Basics)
PPTX
UNIT 4 Total Quality Management .pptx
DOCX
ASol_English-Language-Literature-Set-1-27-02-2023-converted.docx
PPTX
Engineering Ethics, Safety and Environment [Autosaved] (1).pptx
PPTX
M Tech Sem 1 Civil Engineering Environmental Sciences.pptx
PDF
BMEC211 - INTRODUCTION TO MECHATRONICS-1.pdf
PPTX
MET 305 2019 SCHEME MODULE 2 COMPLETE.pptx
PPTX
Welding lecture in detail for understanding
PPTX
Foundation to blockchain - A guide to Blockchain Tech
PDF
PPT on Performance Review to get promotions
PDF
Evaluating the Democratization of the Turkish Armed Forces from a Normative P...
PDF
keyrequirementskkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
PDF
Arduino robotics embedded978-1-4302-3184-4.pdf
PDF
PRIZ Academy - 9 Windows Thinking Where to Invest Today to Win Tomorrow.pdf
PDF
Mohammad Mahdi Farshadian CV - Prospective PhD Student 2026
PPTX
Infosys Presentation by1.Riyan Bagwan 2.Samadhan Naiknavare 3.Gaurav Shinde 4...
PPTX
IOT PPTs Week 10 Lecture Material.pptx of NPTEL Smart Cities contd
PPTX
Internet of Things (IOT) - A guide to understanding
PPTX
CH1 Production IntroductoryConcepts.pptx
PDF
Structs to JSON How Go Powers REST APIs.pdf
OOP with Java - Java Introduction (Basics)
UNIT 4 Total Quality Management .pptx
ASol_English-Language-Literature-Set-1-27-02-2023-converted.docx
Engineering Ethics, Safety and Environment [Autosaved] (1).pptx
M Tech Sem 1 Civil Engineering Environmental Sciences.pptx
BMEC211 - INTRODUCTION TO MECHATRONICS-1.pdf
MET 305 2019 SCHEME MODULE 2 COMPLETE.pptx
Welding lecture in detail for understanding
Foundation to blockchain - A guide to Blockchain Tech
PPT on Performance Review to get promotions
Evaluating the Democratization of the Turkish Armed Forces from a Normative P...
keyrequirementskkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
Arduino robotics embedded978-1-4302-3184-4.pdf
PRIZ Academy - 9 Windows Thinking Where to Invest Today to Win Tomorrow.pdf
Mohammad Mahdi Farshadian CV - Prospective PhD Student 2026
Infosys Presentation by1.Riyan Bagwan 2.Samadhan Naiknavare 3.Gaurav Shinde 4...
IOT PPTs Week 10 Lecture Material.pptx of NPTEL Smart Cities contd
Internet of Things (IOT) - A guide to understanding
CH1 Production IntroductoryConcepts.pptx
Structs to JSON How Go Powers REST APIs.pdf

JavaScript Async for Effortless UX