SlideShare a Scribd company logo
Ensar Bavrk,
Software Developer
@ codecentric
@mrFunkyWisdom
Think async with
JavaScript
Agenda
Concurrency
Agenda
Concurrency
Callbacks
Agenda
Concurrency
Callbacks
Promises
Agenda
Concurrency
Callbacks
Promises
Generatori
Agenda
Concurrency
Callbacks
Promises
Generatori
“Async” funkcije
Uvod, Konkurento i(li) asinhrono izvršavanje
Fundamentalno postoje dva načina procesuiranja više zahtjeva istovremeno a to su
multithreaded sinhroni i asinhroni model (single i multithreaded način)
Jednostavno rečeno “concurrency” znači procesuirati više zahtjeva u isto vrijeme.
Concurrency model in JS
Da je JavaScript hipster, imao bi bradu!
?
Concurrency model in JS
JavaScript ima dosta drugačiji concurrency model od jezika kao što su Java ili Ruby, JavaScript
concurrency model baziran je na "event loop"
Da je JavaScript hipster, imao bi bradu!
Event loop model
Callbacks
Callback
Callback je samo konvencija za JS funkcije. Ne postoji stvar u jeziku zvana 'callback'.
Sam pojam 'asinhrono možemo smatrati kao 'desit će se u budućnosti, ali ne trenutno’. Najčešće callback
funkcije koristimo kod I/O operacija npr. preuzimanje nekog sadržaja, čitanje iz fajlova, komuniciranje sa bazom
podataka, itd.
const sumResult = sum(2, 3)
// sumResult = 5
const cbResult = resource.consume('res://aaa/ss', (err, response) => {/* ... */})
// cbResult = undefined
Sinhroni callback?
Funkcija koju proslijedimo nekoj drugoj funkciji ne mora nužno biti asinhrona.
Razlika da li je funkcija asinhrona ili sinhrona može biti konfuzna, da li je funkcija
sinhrona ili asinhrona zavisi od konteksta.
const numbersArray = [1, 2, 3, 4, 5]
const transformedArray = numbersArray.map(number => number * 2)
console.log(transformedArray)
Callback
hell?
const request = require('request')
const Config = require('../shared/Config')
const getBorrowedBook = cb => {
request.get(Config.USERS_URL, (err, response) => {
if (err) {
cb(err)
}
const { results } = JSON.parse(response.body)
const { 0: { email } } = results
request.get(Config.BASE_URL + encodeURIComponent(email), (err2, response2) => {
if(err2) {
cb(err2)
}
cb(null, response2.body)
})
})
}
getBorrowedBook((err, succes) => {
if(err) {
console.err(err)
} else {
console.log(succes)
}
})
Callback Hell anti-pattern
koji se često pojavljuje u
kodu koji callback funkcije
koriste za orkestriranje
asinhronih operacija.
Promises
Korak u pravom smjeru bi bila apstrakcija asinhronih operacija, a takva apstrakcija
su promisi.
Promises
const futureValue = ms =>
new Promise((resolve) => {
setTimeout(() => resolve('value'), ms)
})
Kreiranje promisa
Executor je funkcija koja se proslijedi promis konstruktoru sa argumentima resolve i
reject
const executor = (resolve, reject) => {
// ... in case of success resolve()
// ... else reject()
}
const promise = new Promise(executor)
Stanja promisa
1. Pending
2. Fulfilled
3. Rejected
Korištenje promisa
Promise.prototype
.then(onFulfilled, onRejected)
Promise.prototype
.catch(onRejected)
const getUsers = () =>
new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
const url = 'https://jsonplaceholder.typicode.com/users'
xhr.open('GET', url)
xhr.onload = () => resolve(xhr.responseText)
xhr.onError= () => reject(xhr.statusText)
xhr.send()
})
getUsers()
.then(response => JSON.parse(response))
.then(users => users.filter(user => !user.name.includes('owe')))
.then(users => users.map(user => ({
name: user.name
})))
.then(console.log)
.catch(console.log)
Promise.prototype.then
.then funkcija prima dvije funkcije kao argumente a to su success i failure handler
funkcije
const onFulfilled = result => console.log(result)
const onRejected = reason => console.log(reason)
getUsers()
.then(onFulfilled, onRejected)
Promise.prototype.then
Najčešće viđamo .then handler, gdje se koristi samo “fulfilled” funkcija
const onFulfilled = result => console.log(result)
const onRejected = reason => console.log(reason)
getUsers()
.then(users => users.filter(user => !user.name.includes('owe')))
.then(users => users.map(user => ({
name: user.name
})))
.then(onFulfilled, onRejected)
Promise.prototype.catch
const onFulfilled = result => console.log(result)
const onRejected = reason => console.log(reason)
getUsers()
.then(users=>users.filter(user=>!user.name.includes('owe')))
.then(users => users.map(user => ({
name: user.name
})))
.then(onFulfilled)
.catch(onRejected)
Promise.race
Promise.race (iterable), vraća promis objekat
Promise.race([promise1, promise2, promise3]).then(console.log)
Promise.race
Primjer korištenja Promise.race
statičke metode
const faker = require('faker');
const fakeRequest = () =>
new Promise((resolve, reject) => {
const randTime = Math.random() * 5000
const randomResponse = {
name: faker.name.findName(),
id: faker.random.number()
}
setTimeout(() => resolve(randomResponse), randTime)
})
const timeToReject = ms =>
new Promise((resolve, reject) =>
setTimeout(() =>
reject(new Error('response takes too long')), ms))
const timedRequest = (request, ms) =>
Promise.race([request, timeToReject(ms)])
timedRequest(fakeRequest(), 2000)
.then(console.log)
.catch(console.log)
Promise.all
const promise1 = Promise.resolve(1)
const promise2 = Promise.resolve(2)
const promise3 = Promise.reject(3)
const all = Promise.all([promise1, promise2, promise3])
all
.then(result => result.map(value => value + 2))
.then(arr => arr.filter(value => value % 2 !== 0))
.then(console.log)
.catch(reason => console.log('rejection reason is ' + reason))
Generatori
Generators
Generatori
Generatori su funkcije koje
dozvoljavaju pauzu, vraćaju
vrijednost i kasnije ponovno
nastavljaju rad i pritom, kontekst tj.
varijabilna vezivanja biće sačuvana
prilikom re-ulaza
function* generatorFunction(){
const number = 7
yield number + 2
yield 5
yield number + 1
}
const generatorObject = generatorFunction()
console.log(generatorObject.next())
for(val of generatorObject){
console.log(val)
}
Generatori
Pozivanjem generator
funkcije, tijelo te funkcije se
neće izvršiti odmah, nego će
vratiti “iterator” objekat, tek
kada se na iterator objektu
pozove next() metoda. Tada
će se izvršiti tijelo generator
funkcije, sve do prvog yield
izraza, što određuje vrijednost
koja će biti vraćena iz
iteratora.
function* generatorFunction() {
let firstNumber = 1, secondNumber = 0
for(let i = 0; i < 50; i++) {
[firstNumber, secondNumber] = [secondNumber, firstNumber]
secondNumber = firstNumber + secondNumber
yield firstNumber
}
}
for(value of generatorFunction()) {
console.log(value)
}
next() metoda može i da primi
vrijednost koja će biti korištena da
promijeni stanje generator funkcije.
Vrijednost koja je proslijeđena next()
funkciji će biti tretirana kao rezultat
posljednjeg pozivanja yield izraza.
Generatori
function* selfEsteeamBooster() {
let name = yield
const sufixes = [
'will rock it today.',
'are so very handsome this morning.',
'is pure gold!'
]
while(true){
yield name + " " + sufixes[
Math.floor(Math.random() * sufixes.length)]
}
}
const message = selfEsteeamBooster()
message.next()
setInterval(() => {
console.log(message.next('Some name').value)
}, 1000)
Generatori i
asinhroni tok
wait(function*() {
try {
const baseURL = 'https://jsonplaceholder.typicode.com/'
const users = yield fetch(baseURL + 'users')
const usersData = yield users.json()
const posts = yield fetch(baseURL + 'posts')
const postsData = yield posts.json()
const allUsers = usersData.map(user => ({
name: user.id,
post: postsData.filter(post => post.userId === user.id)
}))
allUsers.forEach(user => console.log(user))
}
catch(err) {
console.log(err)
}
})
const wait = (it, context) => {
const iter = typeof it === 'function' ? it() : it
iter.next(context).value
.then(rs => wait(iter, rs))
.catch(err => iter.throw(err))
}
Async / Await
Async Await
Poziv asinhrone funkcije vraća Promis objekat. Promis
će biti “riješen” (resolved) sa vrijednosti koju promis
vrati.
Asinhrone funkcije mogu da sadrže await izraze. await
izrazi pauziraju izvršavanje asinhrone funkcije i čekaju
sve dok se proslijeđeni promis ne izvrši (ispuni/odbije),
tek tada asinhrona funkcija nastavlja sa radom.
Await tok
// Koristeći async/await tok izvršavanja
const bookId = await getBookId('javaScript the good parts')
const book = await getFromStore(Resources.BOOKS, bookId)
console.log(book)
// Koristeći promis tok
getBookId('javaScript the good parts')
.then(number => {
getBookFromStore(Resources.BOOKS, number)
.then(book => {
console.log(book)
})
})
Async Await
(async () => {
try {
const baseURL = 'https://jsonplaceholder.typicode.com/'
const users = await fetch(baseURL+'users')
const usersData = await users.json()
const posts = await fetch(baseURL+'posts')
const postsData = await posts.json()
const allUsers = usersData.map(user => ({
name: user.id,
post: postsData.filter(post => post.userId === user.id)
}))
allUsers.forEach(user => console.log(user))
}
catch(err) {
console.log(err)
}
})()
Async&Await i generator “wait” funkcija
wait(function*(){
try {
const baseURL = 'https://jsonplaceholder.typicode.com/'
const users = yield fetch(baseURL+'users')
const usersData = yield users.json()
const posts = yield fetch(baseURL+'posts')
const postsData = yield posts.json()
const allUsers = usersData.map(user => ({
name: user.id,
post: postsData.filter(post => post.userId === user.id)
}))
allUsers.forEach(user => console.log(user))
}
catch(err){
console.log(err)
}
})
(async () => {
try {
const baseURL = 'https://jsonplaceholder.typicode.com/'
const users = await fetch(baseURL+'users')
const usersData = await users.json()
const posts = await fetch(baseURL+'posts')
const postsData = await posts.json()
const allUsers = usersData.map(user => ({
name: user.id,
post: postsData.filter(post => post.userId === user.id)
}))
allUsers.forEach(user => console.log(user))
}
catch(err) {
console.log(err)
}
})()
Unutar async konteksta operacije se
izvršavaju u sekvenci i čekaju
izvršavanje, ali sve izvan tog
asinhronog zadatka ne blokira ostali
kod. Ako želimo da “čekamo” na
izvršavanje nekog asinhronog
“zadatka”, možemo ga pozvati unutar
tog konteksta.
Async “zadaci”
const BASE_URL = 'https://jsonplaceholder.typicode.com/'
const logicalTaskOne = (async () => {
const data = await fetch(BASE_URL+'users');
const result = await data.json()
return result;
})()
const logicalTaskTwo = (async () => {
const data = await fetch(BASE_URL+'photos')
const result = await data.json()
return result;
})()
logicalTaskTwo
.then(console.log)
logicalTaskOne
.then(console.log)
Hvala vam
@mrFunkyWisdom

More Related Content

More from mCloud

Developers’ mDay 2021: Jelena Opačić, mCloud – Dobrodošlica
Developers’ mDay 2021: Jelena Opačić, mCloud – DobrodošlicaDevelopers’ mDay 2021: Jelena Opačić, mCloud – Dobrodošlica
Developers’ mDay 2021: Jelena Opačić, mCloud – Dobrodošlica
mCloud
 
Developers’ mDay 2019. - Zvonimir Gembec, Sysbee – Developers vs Sysadmins – ...
Developers’ mDay 2019. - Zvonimir Gembec, Sysbee – Developers vs Sysadmins – ...Developers’ mDay 2019. - Zvonimir Gembec, Sysbee – Developers vs Sysadmins – ...
Developers’ mDay 2019. - Zvonimir Gembec, Sysbee – Developers vs Sysadmins – ...
mCloud
 
Developers’ mDay 2019. - Dijana Milutinović, RNIDS – Kako se kalio domen
Developers’ mDay 2019. -  Dijana Milutinović, RNIDS – Kako se kalio domenDevelopers’ mDay 2019. -  Dijana Milutinović, RNIDS – Kako se kalio domen
Developers’ mDay 2019. - Dijana Milutinović, RNIDS – Kako se kalio domen
mCloud
 
Developers’ mDay 2019. - Bogdan Kecman, Oracle – MySQL 8.0 – why upgrade
Developers’ mDay 2019. - Bogdan Kecman, Oracle – MySQL 8.0 – why upgradeDevelopers’ mDay 2019. - Bogdan Kecman, Oracle – MySQL 8.0 – why upgrade
Developers’ mDay 2019. - Bogdan Kecman, Oracle – MySQL 8.0 – why upgrade
mCloud
 
Developers’ mDay 2019. - Rastko Vasiljević, SuperAdmins – Infrastructure as c...
Developers’ mDay 2019. - Rastko Vasiljević, SuperAdmins – Infrastructure as c...Developers’ mDay 2019. - Rastko Vasiljević, SuperAdmins – Infrastructure as c...
Developers’ mDay 2019. - Rastko Vasiljević, SuperAdmins – Infrastructure as c...
mCloud
 
Developers’ mDay 2019. - Dejan Bosanac, Red Hat – Cloud scale IoT connectivity
Developers’ mDay 2019. - Dejan Bosanac, Red Hat – Cloud scale IoT connectivityDevelopers’ mDay 2019. - Dejan Bosanac, Red Hat – Cloud scale IoT connectivity
Developers’ mDay 2019. - Dejan Bosanac, Red Hat – Cloud scale IoT connectivity
mCloud
 
Developers’ mDay 2019. - Adrian Smijulj, Webiny – Server-side rendering u Ser...
Developers’ mDay 2019. - Adrian Smijulj, Webiny – Server-side rendering u Ser...Developers’ mDay 2019. - Adrian Smijulj, Webiny – Server-side rendering u Ser...
Developers’ mDay 2019. - Adrian Smijulj, Webiny – Server-side rendering u Ser...
mCloud
 
Developers’ mDay 2019. - Nikola Krgović, Twin Star Systems – Big Data for Dev...
Developers’ mDay 2019. - Nikola Krgović, Twin Star Systems – Big Data for Dev...Developers’ mDay 2019. - Nikola Krgović, Twin Star Systems – Big Data for Dev...
Developers’ mDay 2019. - Nikola Krgović, Twin Star Systems – Big Data for Dev...
mCloud
 
Developers’ mDay 2019. - Dragutin Ćirković, mCloud – HTTP/3
Developers’ mDay 2019. - Dragutin Ćirković, mCloud – HTTP/3Developers’ mDay 2019. - Dragutin Ćirković, mCloud – HTTP/3
Developers’ mDay 2019. - Dragutin Ćirković, mCloud – HTTP/3
mCloud
 
Developers’ mDay u Banjoj Luci - Janko Isidorović, Mainflux – Unified IoT Pl...
Developers’ mDay u Banjoj Luci - Janko Isidorović, Mainflux –  Unified IoT Pl...Developers’ mDay u Banjoj Luci - Janko Isidorović, Mainflux –  Unified IoT Pl...
Developers’ mDay u Banjoj Luci - Janko Isidorović, Mainflux – Unified IoT Pl...
mCloud
 
Developers’ mDay u Banjoj Luci - Jelena Opačić, mCloud – Dobrodošlica
Developers’ mDay u Banjoj Luci - Jelena Opačić, mCloud – DobrodošlicaDevelopers’ mDay u Banjoj Luci - Jelena Opačić, mCloud – Dobrodošlica
Developers’ mDay u Banjoj Luci - Jelena Opačić, mCloud – Dobrodošlica
mCloud
 
Developers’ mDay u Banjoj Luci - Duško Bajić, Kotlin User Group Bosnia – Kotl...
Developers’ mDay u Banjoj Luci - Duško Bajić, Kotlin User Group Bosnia – Kotl...Developers’ mDay u Banjoj Luci - Duško Bajić, Kotlin User Group Bosnia – Kotl...
Developers’ mDay u Banjoj Luci - Duško Bajić, Kotlin User Group Bosnia – Kotl...
mCloud
 
Developers’ mDay u Banjoj Luci - Ivan Đukić, ECD, Blockchain & Cryptocurrency...
Developers’ mDay u Banjoj Luci - Ivan Đukić, ECD, Blockchain & Cryptocurrency...Developers’ mDay u Banjoj Luci - Ivan Đukić, ECD, Blockchain & Cryptocurrency...
Developers’ mDay u Banjoj Luci - Ivan Đukić, ECD, Blockchain & Cryptocurrency...
mCloud
 
Developers’ mDay u Banjoj Luci - Boris Vezmar, SuperAdmins – Simple sysadmin ...
Developers’ mDay u Banjoj Luci - Boris Vezmar, SuperAdmins – Simple sysadmin ...Developers’ mDay u Banjoj Luci - Boris Vezmar, SuperAdmins – Simple sysadmin ...
Developers’ mDay u Banjoj Luci - Boris Vezmar, SuperAdmins – Simple sysadmin ...
mCloud
 
Developers’ mDay u Banjoj Luci - Milan Popović, PHP Srbija – Testimony (about...
Developers’ mDay u Banjoj Luci - Milan Popović, PHP Srbija – Testimony (about...Developers’ mDay u Banjoj Luci - Milan Popović, PHP Srbija – Testimony (about...
Developers’ mDay u Banjoj Luci - Milan Popović, PHP Srbija – Testimony (about...
mCloud
 
Developers’ mDay u Banjoj Luci - Bogdan Kecman, Oracle – MySQL Server 8.0
Developers’ mDay u Banjoj Luci - Bogdan Kecman, Oracle – MySQL Server 8.0Developers’ mDay u Banjoj Luci - Bogdan Kecman, Oracle – MySQL Server 8.0
Developers’ mDay u Banjoj Luci - Bogdan Kecman, Oracle – MySQL Server 8.0
mCloud
 
Developers' mDay 2017. - Bogdan Kecman Oracle
Developers' mDay 2017. - Bogdan Kecman OracleDevelopers' mDay 2017. - Bogdan Kecman Oracle
Developers' mDay 2017. - Bogdan Kecman Oracle
mCloud
 
Developers' mDay 2017. - Ilija Studen ActiveCollab
Developers' mDay 2017. - Ilija Studen ActiveCollabDevelopers' mDay 2017. - Ilija Studen ActiveCollab
Developers' mDay 2017. - Ilija Studen ActiveCollab
mCloud
 
Developers' mDay 2017. - Miloš Marčeta Telegraf.rs
Developers' mDay 2017. - Miloš Marčeta Telegraf.rsDevelopers' mDay 2017. - Miloš Marčeta Telegraf.rs
Developers' mDay 2017. - Miloš Marčeta Telegraf.rs
mCloud
 
Developers' mDay 2017. - Aleksandar Matanović EDC
Developers' mDay 2017. - Aleksandar Matanović EDCDevelopers' mDay 2017. - Aleksandar Matanović EDC
Developers' mDay 2017. - Aleksandar Matanović EDC
mCloud
 

More from mCloud (20)

Developers’ mDay 2021: Jelena Opačić, mCloud – Dobrodošlica
Developers’ mDay 2021: Jelena Opačić, mCloud – DobrodošlicaDevelopers’ mDay 2021: Jelena Opačić, mCloud – Dobrodošlica
Developers’ mDay 2021: Jelena Opačić, mCloud – Dobrodošlica
 
Developers’ mDay 2019. - Zvonimir Gembec, Sysbee – Developers vs Sysadmins – ...
Developers’ mDay 2019. - Zvonimir Gembec, Sysbee – Developers vs Sysadmins – ...Developers’ mDay 2019. - Zvonimir Gembec, Sysbee – Developers vs Sysadmins – ...
Developers’ mDay 2019. - Zvonimir Gembec, Sysbee – Developers vs Sysadmins – ...
 
Developers’ mDay 2019. - Dijana Milutinović, RNIDS – Kako se kalio domen
Developers’ mDay 2019. -  Dijana Milutinović, RNIDS – Kako se kalio domenDevelopers’ mDay 2019. -  Dijana Milutinović, RNIDS – Kako se kalio domen
Developers’ mDay 2019. - Dijana Milutinović, RNIDS – Kako se kalio domen
 
Developers’ mDay 2019. - Bogdan Kecman, Oracle – MySQL 8.0 – why upgrade
Developers’ mDay 2019. - Bogdan Kecman, Oracle – MySQL 8.0 – why upgradeDevelopers’ mDay 2019. - Bogdan Kecman, Oracle – MySQL 8.0 – why upgrade
Developers’ mDay 2019. - Bogdan Kecman, Oracle – MySQL 8.0 – why upgrade
 
Developers’ mDay 2019. - Rastko Vasiljević, SuperAdmins – Infrastructure as c...
Developers’ mDay 2019. - Rastko Vasiljević, SuperAdmins – Infrastructure as c...Developers’ mDay 2019. - Rastko Vasiljević, SuperAdmins – Infrastructure as c...
Developers’ mDay 2019. - Rastko Vasiljević, SuperAdmins – Infrastructure as c...
 
Developers’ mDay 2019. - Dejan Bosanac, Red Hat – Cloud scale IoT connectivity
Developers’ mDay 2019. - Dejan Bosanac, Red Hat – Cloud scale IoT connectivityDevelopers’ mDay 2019. - Dejan Bosanac, Red Hat – Cloud scale IoT connectivity
Developers’ mDay 2019. - Dejan Bosanac, Red Hat – Cloud scale IoT connectivity
 
Developers’ mDay 2019. - Adrian Smijulj, Webiny – Server-side rendering u Ser...
Developers’ mDay 2019. - Adrian Smijulj, Webiny – Server-side rendering u Ser...Developers’ mDay 2019. - Adrian Smijulj, Webiny – Server-side rendering u Ser...
Developers’ mDay 2019. - Adrian Smijulj, Webiny – Server-side rendering u Ser...
 
Developers’ mDay 2019. - Nikola Krgović, Twin Star Systems – Big Data for Dev...
Developers’ mDay 2019. - Nikola Krgović, Twin Star Systems – Big Data for Dev...Developers’ mDay 2019. - Nikola Krgović, Twin Star Systems – Big Data for Dev...
Developers’ mDay 2019. - Nikola Krgović, Twin Star Systems – Big Data for Dev...
 
Developers’ mDay 2019. - Dragutin Ćirković, mCloud – HTTP/3
Developers’ mDay 2019. - Dragutin Ćirković, mCloud – HTTP/3Developers’ mDay 2019. - Dragutin Ćirković, mCloud – HTTP/3
Developers’ mDay 2019. - Dragutin Ćirković, mCloud – HTTP/3
 
Developers’ mDay u Banjoj Luci - Janko Isidorović, Mainflux – Unified IoT Pl...
Developers’ mDay u Banjoj Luci - Janko Isidorović, Mainflux –  Unified IoT Pl...Developers’ mDay u Banjoj Luci - Janko Isidorović, Mainflux –  Unified IoT Pl...
Developers’ mDay u Banjoj Luci - Janko Isidorović, Mainflux – Unified IoT Pl...
 
Developers’ mDay u Banjoj Luci - Jelena Opačić, mCloud – Dobrodošlica
Developers’ mDay u Banjoj Luci - Jelena Opačić, mCloud – DobrodošlicaDevelopers’ mDay u Banjoj Luci - Jelena Opačić, mCloud – Dobrodošlica
Developers’ mDay u Banjoj Luci - Jelena Opačić, mCloud – Dobrodošlica
 
Developers’ mDay u Banjoj Luci - Duško Bajić, Kotlin User Group Bosnia – Kotl...
Developers’ mDay u Banjoj Luci - Duško Bajić, Kotlin User Group Bosnia – Kotl...Developers’ mDay u Banjoj Luci - Duško Bajić, Kotlin User Group Bosnia – Kotl...
Developers’ mDay u Banjoj Luci - Duško Bajić, Kotlin User Group Bosnia – Kotl...
 
Developers’ mDay u Banjoj Luci - Ivan Đukić, ECD, Blockchain & Cryptocurrency...
Developers’ mDay u Banjoj Luci - Ivan Đukić, ECD, Blockchain & Cryptocurrency...Developers’ mDay u Banjoj Luci - Ivan Đukić, ECD, Blockchain & Cryptocurrency...
Developers’ mDay u Banjoj Luci - Ivan Đukić, ECD, Blockchain & Cryptocurrency...
 
Developers’ mDay u Banjoj Luci - Boris Vezmar, SuperAdmins – Simple sysadmin ...
Developers’ mDay u Banjoj Luci - Boris Vezmar, SuperAdmins – Simple sysadmin ...Developers’ mDay u Banjoj Luci - Boris Vezmar, SuperAdmins – Simple sysadmin ...
Developers’ mDay u Banjoj Luci - Boris Vezmar, SuperAdmins – Simple sysadmin ...
 
Developers’ mDay u Banjoj Luci - Milan Popović, PHP Srbija – Testimony (about...
Developers’ mDay u Banjoj Luci - Milan Popović, PHP Srbija – Testimony (about...Developers’ mDay u Banjoj Luci - Milan Popović, PHP Srbija – Testimony (about...
Developers’ mDay u Banjoj Luci - Milan Popović, PHP Srbija – Testimony (about...
 
Developers’ mDay u Banjoj Luci - Bogdan Kecman, Oracle – MySQL Server 8.0
Developers’ mDay u Banjoj Luci - Bogdan Kecman, Oracle – MySQL Server 8.0Developers’ mDay u Banjoj Luci - Bogdan Kecman, Oracle – MySQL Server 8.0
Developers’ mDay u Banjoj Luci - Bogdan Kecman, Oracle – MySQL Server 8.0
 
Developers' mDay 2017. - Bogdan Kecman Oracle
Developers' mDay 2017. - Bogdan Kecman OracleDevelopers' mDay 2017. - Bogdan Kecman Oracle
Developers' mDay 2017. - Bogdan Kecman Oracle
 
Developers' mDay 2017. - Ilija Studen ActiveCollab
Developers' mDay 2017. - Ilija Studen ActiveCollabDevelopers' mDay 2017. - Ilija Studen ActiveCollab
Developers' mDay 2017. - Ilija Studen ActiveCollab
 
Developers' mDay 2017. - Miloš Marčeta Telegraf.rs
Developers' mDay 2017. - Miloš Marčeta Telegraf.rsDevelopers' mDay 2017. - Miloš Marčeta Telegraf.rs
Developers' mDay 2017. - Miloš Marčeta Telegraf.rs
 
Developers' mDay 2017. - Aleksandar Matanović EDC
Developers' mDay 2017. - Aleksandar Matanović EDCDevelopers' mDay 2017. - Aleksandar Matanović EDC
Developers' mDay 2017. - Aleksandar Matanović EDC
 

Developers’ mDay u Banjoj Luci - Ensar Bavrk, codecentric – Think async with JavaScript

  • 1. Ensar Bavrk, Software Developer @ codecentric @mrFunkyWisdom Think async with JavaScript
  • 7. Uvod, Konkurento i(li) asinhrono izvršavanje Fundamentalno postoje dva načina procesuiranja više zahtjeva istovremeno a to su multithreaded sinhroni i asinhroni model (single i multithreaded način) Jednostavno rečeno “concurrency” znači procesuirati više zahtjeva u isto vrijeme.
  • 8. Concurrency model in JS Da je JavaScript hipster, imao bi bradu! ?
  • 9. Concurrency model in JS JavaScript ima dosta drugačiji concurrency model od jezika kao što su Java ili Ruby, JavaScript concurrency model baziran je na "event loop" Da je JavaScript hipster, imao bi bradu!
  • 12. Callback Callback je samo konvencija za JS funkcije. Ne postoji stvar u jeziku zvana 'callback'. Sam pojam 'asinhrono možemo smatrati kao 'desit će se u budućnosti, ali ne trenutno’. Najčešće callback funkcije koristimo kod I/O operacija npr. preuzimanje nekog sadržaja, čitanje iz fajlova, komuniciranje sa bazom podataka, itd. const sumResult = sum(2, 3) // sumResult = 5 const cbResult = resource.consume('res://aaa/ss', (err, response) => {/* ... */}) // cbResult = undefined
  • 13. Sinhroni callback? Funkcija koju proslijedimo nekoj drugoj funkciji ne mora nužno biti asinhrona. Razlika da li je funkcija asinhrona ili sinhrona može biti konfuzna, da li je funkcija sinhrona ili asinhrona zavisi od konteksta. const numbersArray = [1, 2, 3, 4, 5] const transformedArray = numbersArray.map(number => number * 2) console.log(transformedArray)
  • 14. Callback hell? const request = require('request') const Config = require('../shared/Config') const getBorrowedBook = cb => { request.get(Config.USERS_URL, (err, response) => { if (err) { cb(err) } const { results } = JSON.parse(response.body) const { 0: { email } } = results request.get(Config.BASE_URL + encodeURIComponent(email), (err2, response2) => { if(err2) { cb(err2) } cb(null, response2.body) }) }) } getBorrowedBook((err, succes) => { if(err) { console.err(err) } else { console.log(succes) } }) Callback Hell anti-pattern koji se često pojavljuje u kodu koji callback funkcije koriste za orkestriranje asinhronih operacija.
  • 16. Korak u pravom smjeru bi bila apstrakcija asinhronih operacija, a takva apstrakcija su promisi. Promises const futureValue = ms => new Promise((resolve) => { setTimeout(() => resolve('value'), ms) })
  • 17. Kreiranje promisa Executor je funkcija koja se proslijedi promis konstruktoru sa argumentima resolve i reject const executor = (resolve, reject) => { // ... in case of success resolve() // ... else reject() } const promise = new Promise(executor)
  • 18. Stanja promisa 1. Pending 2. Fulfilled 3. Rejected
  • 19. Korištenje promisa Promise.prototype .then(onFulfilled, onRejected) Promise.prototype .catch(onRejected) const getUsers = () => new Promise((resolve, reject) => { const xhr = new XMLHttpRequest() const url = 'https://jsonplaceholder.typicode.com/users' xhr.open('GET', url) xhr.onload = () => resolve(xhr.responseText) xhr.onError= () => reject(xhr.statusText) xhr.send() }) getUsers() .then(response => JSON.parse(response)) .then(users => users.filter(user => !user.name.includes('owe'))) .then(users => users.map(user => ({ name: user.name }))) .then(console.log) .catch(console.log)
  • 20. Promise.prototype.then .then funkcija prima dvije funkcije kao argumente a to su success i failure handler funkcije const onFulfilled = result => console.log(result) const onRejected = reason => console.log(reason) getUsers() .then(onFulfilled, onRejected)
  • 21. Promise.prototype.then Najčešće viđamo .then handler, gdje se koristi samo “fulfilled” funkcija const onFulfilled = result => console.log(result) const onRejected = reason => console.log(reason) getUsers() .then(users => users.filter(user => !user.name.includes('owe'))) .then(users => users.map(user => ({ name: user.name }))) .then(onFulfilled, onRejected)
  • 22. Promise.prototype.catch const onFulfilled = result => console.log(result) const onRejected = reason => console.log(reason) getUsers() .then(users=>users.filter(user=>!user.name.includes('owe'))) .then(users => users.map(user => ({ name: user.name }))) .then(onFulfilled) .catch(onRejected)
  • 23. Promise.race Promise.race (iterable), vraća promis objekat Promise.race([promise1, promise2, promise3]).then(console.log)
  • 24. Promise.race Primjer korištenja Promise.race statičke metode const faker = require('faker'); const fakeRequest = () => new Promise((resolve, reject) => { const randTime = Math.random() * 5000 const randomResponse = { name: faker.name.findName(), id: faker.random.number() } setTimeout(() => resolve(randomResponse), randTime) }) const timeToReject = ms => new Promise((resolve, reject) => setTimeout(() => reject(new Error('response takes too long')), ms)) const timedRequest = (request, ms) => Promise.race([request, timeToReject(ms)]) timedRequest(fakeRequest(), 2000) .then(console.log) .catch(console.log)
  • 25. Promise.all const promise1 = Promise.resolve(1) const promise2 = Promise.resolve(2) const promise3 = Promise.reject(3) const all = Promise.all([promise1, promise2, promise3]) all .then(result => result.map(value => value + 2)) .then(arr => arr.filter(value => value % 2 !== 0)) .then(console.log) .catch(reason => console.log('rejection reason is ' + reason))
  • 27. Generatori Generatori su funkcije koje dozvoljavaju pauzu, vraćaju vrijednost i kasnije ponovno nastavljaju rad i pritom, kontekst tj. varijabilna vezivanja biće sačuvana prilikom re-ulaza function* generatorFunction(){ const number = 7 yield number + 2 yield 5 yield number + 1 } const generatorObject = generatorFunction() console.log(generatorObject.next()) for(val of generatorObject){ console.log(val) }
  • 28. Generatori Pozivanjem generator funkcije, tijelo te funkcije se neće izvršiti odmah, nego će vratiti “iterator” objekat, tek kada se na iterator objektu pozove next() metoda. Tada će se izvršiti tijelo generator funkcije, sve do prvog yield izraza, što određuje vrijednost koja će biti vraćena iz iteratora. function* generatorFunction() { let firstNumber = 1, secondNumber = 0 for(let i = 0; i < 50; i++) { [firstNumber, secondNumber] = [secondNumber, firstNumber] secondNumber = firstNumber + secondNumber yield firstNumber } } for(value of generatorFunction()) { console.log(value) }
  • 29. next() metoda može i da primi vrijednost koja će biti korištena da promijeni stanje generator funkcije. Vrijednost koja je proslijeđena next() funkciji će biti tretirana kao rezultat posljednjeg pozivanja yield izraza. Generatori function* selfEsteeamBooster() { let name = yield const sufixes = [ 'will rock it today.', 'are so very handsome this morning.', 'is pure gold!' ] while(true){ yield name + " " + sufixes[ Math.floor(Math.random() * sufixes.length)] } } const message = selfEsteeamBooster() message.next() setInterval(() => { console.log(message.next('Some name').value) }, 1000)
  • 30. Generatori i asinhroni tok wait(function*() { try { const baseURL = 'https://jsonplaceholder.typicode.com/' const users = yield fetch(baseURL + 'users') const usersData = yield users.json() const posts = yield fetch(baseURL + 'posts') const postsData = yield posts.json() const allUsers = usersData.map(user => ({ name: user.id, post: postsData.filter(post => post.userId === user.id) })) allUsers.forEach(user => console.log(user)) } catch(err) { console.log(err) } }) const wait = (it, context) => { const iter = typeof it === 'function' ? it() : it iter.next(context).value .then(rs => wait(iter, rs)) .catch(err => iter.throw(err)) }
  • 32. Async Await Poziv asinhrone funkcije vraća Promis objekat. Promis će biti “riješen” (resolved) sa vrijednosti koju promis vrati. Asinhrone funkcije mogu da sadrže await izraze. await izrazi pauziraju izvršavanje asinhrone funkcije i čekaju sve dok se proslijeđeni promis ne izvrši (ispuni/odbije), tek tada asinhrona funkcija nastavlja sa radom.
  • 33. Await tok // Koristeći async/await tok izvršavanja const bookId = await getBookId('javaScript the good parts') const book = await getFromStore(Resources.BOOKS, bookId) console.log(book) // Koristeći promis tok getBookId('javaScript the good parts') .then(number => { getBookFromStore(Resources.BOOKS, number) .then(book => { console.log(book) }) })
  • 34. Async Await (async () => { try { const baseURL = 'https://jsonplaceholder.typicode.com/' const users = await fetch(baseURL+'users') const usersData = await users.json() const posts = await fetch(baseURL+'posts') const postsData = await posts.json() const allUsers = usersData.map(user => ({ name: user.id, post: postsData.filter(post => post.userId === user.id) })) allUsers.forEach(user => console.log(user)) } catch(err) { console.log(err) } })()
  • 35. Async&Await i generator “wait” funkcija wait(function*(){ try { const baseURL = 'https://jsonplaceholder.typicode.com/' const users = yield fetch(baseURL+'users') const usersData = yield users.json() const posts = yield fetch(baseURL+'posts') const postsData = yield posts.json() const allUsers = usersData.map(user => ({ name: user.id, post: postsData.filter(post => post.userId === user.id) })) allUsers.forEach(user => console.log(user)) } catch(err){ console.log(err) } }) (async () => { try { const baseURL = 'https://jsonplaceholder.typicode.com/' const users = await fetch(baseURL+'users') const usersData = await users.json() const posts = await fetch(baseURL+'posts') const postsData = await posts.json() const allUsers = usersData.map(user => ({ name: user.id, post: postsData.filter(post => post.userId === user.id) })) allUsers.forEach(user => console.log(user)) } catch(err) { console.log(err) } })()
  • 36. Unutar async konteksta operacije se izvršavaju u sekvenci i čekaju izvršavanje, ali sve izvan tog asinhronog zadatka ne blokira ostali kod. Ako želimo da “čekamo” na izvršavanje nekog asinhronog “zadatka”, možemo ga pozvati unutar tog konteksta. Async “zadaci” const BASE_URL = 'https://jsonplaceholder.typicode.com/' const logicalTaskOne = (async () => { const data = await fetch(BASE_URL+'users'); const result = await data.json() return result; })() const logicalTaskTwo = (async () => { const data = await fetch(BASE_URL+'photos') const result = await data.json() return result; })() logicalTaskTwo .then(console.log) logicalTaskOne .then(console.log)