Promise (osnove)

Uvod


pyramid of doom

U JavaScript-u postoji izraz za deo koda sa ugnježdenim callback funkcijama pod nazivom “callback hell” ili “pyramid of doom”. Debagovanje takvog programskog koda pa čak i samo razumevanje je veoma otežano. Sa ES2015 standardom je došla nova syntax-a pod nazivom “promise” (srp. obećanje), koja sa svojim API-jem obezbedjuje bolji i pregledniji način za organizovanje callback funkcija. Ovo se naručito primećuje u radu sa asinhronim operacijama jer sa promisima sintaksa veoma liči na standardnu sinhronu sintaksu.

Primer – “callback hell”

Najpoznatija i najčešća primena callback funkcija je “hendlovanje” akcija nakon izvršenog dogadjaja. Upravo je “hendlovanje” medjusobno zavisnih dogadjaja najčešće uzrok “callback hell-a”. U ovom primeru je prikazan izgled takvog koda:


Continue reading…


Klase u JavaScript-u

Uvod

Klase u javascript-u

Klase u JavaScript-u su samo drugačiji način predstavljanja konstruktorske funkcije i metoda iz “prototype objekata”, ali bez suštinske promene samog mehanizama nasledjivanja. Pozadina nasledjivanje klasa je poznati mehanizam “delegiranje metoda” kroz “prototype lanac nasledjivanja”.
U JavaScript-u rezervisana reč “class” samo ukazuje na to da je upitanju specijalna vrsta funkcije, koja za razliku od obične funkcije ne može da se pozove (invoke), nego se jedino može koristiti uz rezervisanu reč “new”.
Ova funkcionalnost je ubačena u jezik sa ES2015 standardom, sa namerom da poboljša čitljivost i olakša pisanje objektno orjentisanih programa. Pri definisanju izgleda sinktakse dizajneri standarda su se vodili idejom da naprave takvu sinktaksu koja će ličiti na sinktaksu većine “klasnih” jezika”, i tako pomoći programerima koji već programiraju u nekom “klasnom” jeziku” da lakše usvoje JavaScript sinktaksu.
Ako u narednim primerima uporedimo delove koda pisane različitim sintaksama, možemo uočiti da je bolja čitljivost klasne sintakse u odnosu na ES5 sintaksu:

Primer: ES5 sintaksa

Primer: Klasna sintaksa

Izgled klase je veoma sličan sintaksi kreiranja objekta prema ES5 standardu, mada je čitljiviji zbog manje redova i izbačenih nepotrebnih delova:

NAPOMENA:
Za razliku od drugih “klasnih jezika”, kreiranje objekata u Javascript-u (čak i kada se koriste klase) nije statičko tj. nije nepromenjivo nakon deklarisanja objekta. U JavaScript-u objekat nakon instanciranja ostaje “vezan” za klasu, svojim “prototype objektom” preko lanca nasledjivanja. Stoga, ukoliko naknadno dodamo ili promenimo neku metodu u samoj klasi, tu promenu će osetiti svaki objekat instanciran na osnovu te klase.

Continue reading…


Prototipsko nasledjivanje

Uvod

Prototipsko nasledjivanje (eng. prototypal inheritance) je vrsta nasledjivanja gde objekat nasledjuje svojstva direktno od drugog objekta (ne od nekogo šablona tj. klase). Postoje dva osnovna mehanizma koji omogućavaju prototipsko nasledjivanje:

  1. Concatenative inheritance
    Ovaj proces se zasniva na direktnom kopiranju svojstva jednog ili više objekata u novi objekat. Treba napomenuti da je za kopiranje svojstva neophodno da enumerable deskriptor svojstva bude setovan na true. Ovaj mehanizam je prihvaćen i sa standardom ES2015, uz pomoć metode “Object.assign()”.
  2. Prototipsko delegiranje
    Ovaj proces se zasniva se na principu da se svojstva i metode nasledjuju kroz “lanac povezanih prototype objekata” (eng. “prototype chain”).

NAPOMENA:
Uokviru standarda ES2015 je predstavljena syntax-a za kreiranje objekata preko klasa, medjutim to je samo estetska promena jer se u pozadini sav posao oko nasledivanja izvršava prema prethodno pomenutom mehanizmu “prototipsko delegiranje”.

Continue reading…


AJAX sa plain JavaScript-om

Uvod

ajax

Ajax je skraćenica od “Asinhroni JavaScript + XML” (iako se danas uglavnom koristi JSON), a predstavlja grupu tehnologija namenjenu za dinamičko kreiranje Web stranica. Korišćenjem AJAX-a poboljšavamo kvalitet interkativnosti sa korisnikom, uz želju da što više liči na desktop aplikacije (prema brzini interakcije). Ideja na kojoj se zasniva Ajax jeste da se stranica na kojoj se odvija Web aplikacija učita samo jednom, a da se svaka dalja komunikacija sa serverom izvršava asinhrono bez blokiranja interfejsa i bez ponovnog učitavanja čitave stranice. Asinhrono ponašanje podrazumeva da nakon interakcije korisnika sa interfejsom, zahtev ka serveru prihvata JavaScript i XMLHttpRequest objekat, koji u pozadini šalje zahteve serveru a prikazujući rezultate kada budu raspoloživi, dok korisnik u međuvremenu može da nastavi sa radom.

Ajax nije bez mana, budući da se Ajax stranice dinamički generišu najveći problem za sajtove je optimizacija za pretraživače. Pretraživači često ne mogu dobro da protumače sajt, što dovodi do problema u indeksiranju sajtova. Sličan problem postoji i sa alatima za analizu posećenosti stranica, jer korisnik može ceo dan da provede na jednoj Ajax stranici, a klasični alati za analizu posećenosti će to protumačiti kao jedno prikazivanje stranice.

Continue reading…


Cross Domain DATA Request

Definicija

Cross Domain Data Request predstavlja specifičan zahtev za podacima, jer se podaci ne nalaze na domenu (protokolu ili portu) odakle potiče i sam zahtev.

cors

Podrazumevano ponašanje servera je da ne dozvoljavaju pristup podacima sa drugih servera, a glavni razlog ove zabrane je mogućnosti da se vrše napredni zahtevi (POST, PUT i DELETE itd.) koji mogu dovesti do raznih bezbednosnih problema. Stoga su i AJAX zahtevi podrazumevano zabranjeni, a to ogranicenje je poznato pod nazivom the same origin policy (srp. polisa zajedničkog porekla).
Medjutim neke vrste resursa ipak ne podležu ovoj zabrani, jer im pregledači podrazumevano dozvoljavaju pristup. Resurse koji se ne nalaze na domenu odakle potiče i sam zahtev je dozvoljeno pozvati jedino kroz “src” ili “href” atribute sledećih HTML elemenata: <script>, <img>, <video>, <iframe>.

Postoje rešenja i za zahteve kod kojih važi zabrana “the same origin policy“, ali to podrazumeva korišćenje specifičnih mehanizama. Upravo o tim mehanizmima je reč u ovom članku.

Continue reading…


Princip rada asinhronog JavaScript-a

Uvod

asihrono programiranje

Pri sinhronom izvršavanju operacija, trenutna operacija mora da se završi da bi naredna počela da se izvršava. Dok kod asihronog izvršavanja, operacije ne čekaju jedna drugu da se izvrše, nego se izvršavaju istovremeno. Generalno u većini slučajeva sinhronomi procesi nisu problem jer su kompjuteri veoma brzi pa se sve operacije izvršavaju skoro instant. Medjutim kod web-a su problem upiti ka serveru. Ukoliko bi ovi procesi bili sinhroni, ceo interfejs web aplikacije bi bio “smrznut” dok ne stigne odgovor servera. Isto važi za I/O operacije sa podacima. Rezultat toga je da se ukupno asinhrone operacije brže izvršavaju iako svaka pojedinačno ništa nije brža nego kod sinhronih operacija. (Pogledaj sliku)

JavaScript i asinhrono programiranje

asnhorni JS okruzenje

JavaScript je “single thread” programski jezik i on sam ne može da izvršava više istovremenih paralelnih radnji. JavaScript je takodje i skriptni jezik stoga je neophodno da se “smesti” u neki kontejner koji bi mu omogućio rad, taj kontejner se zove JS Runtime Environment (srp. okruženje). Upravo je to okruženje zaslužno za izvršavanje više paralelnih radnji istovremeno (tzv. asihrono izvršavanje). Ključni delovi zaduženi za asihroni rad JS-a su “External API”, i “Event loop”. Stoga da bi razumeli kako JavaScript obradjuje asinhrone operacije, neophodno je prvo upoznati osnovne elemente Runtime Enviroment-a.

Postoje dva tipa okruženja: browser (za rad na klijentu) i node.js (za rad na serveru). Runtime Environment čine :

  1. JS Engine/Runtime
    • Heap
    • Stack
  2. External API
  3. Queue
  4. Event loop

Više o JS Runtime Enviroment-u pročitajte u članku “JavaScript i njegovo okruženje”

Koji su procesi asinhroni u JavaScriptu?

a) Izvršavanje setTimeout() metode

Asihrono programiranje sa odgovarajućim external API-jem je najlakše objasniti kroz primere. Naredni primer se izvršava u browseru, a kod sadrži dve metode za štampanje teksta u konzoli i jednu specijalnu metodu setTimeout() koja je deo objekta Window (WebAPI).

Primer

JS izvšava kod liniju po liniju, prvo stavi na stack prvu console.log() metodu i zatim je izvrši. Nakon čega JS engine dolazi do reda gde se poziva setTimeout(), pa ovu metodu stavlja na vrh stack-a i izvršava je.

eventloop1

Ovde počinje interesantni deo jer nakon izvršenja setTimeout() metode ona se sklanja sa stack-a, a njena callback funkcija se prebacuje u sekciju webAPI i uključuje tajmer. Nakon toga JS engine nastavlja sa obradom naredne linije koda gde nailazi na drugu console.log() metodu koju stavlja na stack i izvršava je.

eventloop2

Dok se izvršava ostali deo programa, a po isteku vremena zadatog u tajmeru callback funkcija se prebacuje na task queue i tamo čeka da se stack izprazni da bi mogla da se izrši.

evemtloop3

Event loop će prebaciti task (callback funkciju) iz task queue samo ako je prazan stack.

eventloop4

Kada se callback funkcija nadje na stack-u izvršava se i nakon toga sklanja sa stack-a. Rezultat izvšavanja ovog koda je štampanje teksta u konzoli ovim redosledom:

  1. Prva console.log() metoda štampa: “Hi”
  2. Treća console.log() metoda štampa: “JSconfEU
  3. Druga console.log() metoda u okviru setTimout() metode štampa: “there

NAPOMENA:
Odlaganje callback funkcije za nula sekundi ne podrazumeva da će odmah da se izvrši. Callback funkcija mora da predje isti put kao i u prethodnom primeru (stack -> web API -> task queue -> stack), stim što će se u web APi sekciji zadržati nula sekundi. Medjutim u task queue će morati da sačeka dok se se stack ne isprazni. Ova “fora” se koristi kada želimo da se sinhroni proces postane asinhroni, tako što callback funkciju omotamo sa setTimout() metodom, a kao parametar stavimo 0ms.

Pogledajte animaciju ovog primera ovde (Savet: kliknite na ikonicu dva ukrštena čekića u gornjem levom uglu aplikacije da promenite brzinu izvršavanja koda).

b) Zahtev podataka sa servera

Pored tajmera koji omogućavaju asinhrono programiranje, asihron je i poziv serveru uz pomoć XMLHttpRequest objekta. Na sledećem primeru ćemo objasniti kako asinhrono funcioniše JavaScript pri pozivu servera:

Primer

Prvo se izvšava prva linija koda zbog čega se prebacuje na stack

server call

Kada se izvrši prva naredba ona se sklanja sa stack-a i izvršava se naredna a to je get() metoda koja bi trebalo da asinhrono “dovuče” podatke sa servera koristeći “HTTP GET request“.

server call

Kad se izvrši metoda get(), ona se sklanja sa stack-a, dok “callback” funkcija stoji sa strane i tako ne koči dalje izvršavanje JavaScript koda dok čeka podatke.

server call

Dok callback funkcija čeka podatke, paralelno se izvršava poslednja linija koda koja štampa u konzoli neki tekst.

server call

Kada je ištampan teks i izvršena poslednja naredba, ona se sklanja sa stack-a koji ostaje prazan. Za to vreme je callback funkcija dobila podatke i smestila se u red za čekanje “queue”.

server call

Čim se oslobodio stack, event loop prebacuje callback funkciju na stack i izvršava je.

server call

Rezultat izvšavanja ovog koda je štampanje teksta u konzoli ovim redosledom:

  1. Prva console.log() metoda štampa: “Hi”
  2. Treća console.log() metoda štampa: “SJS
  3. Druga console.log() metoda u okviru setTimout() metode štampa podatke sa servera

c) Dogadjaji se izvršavaju asinhrono

Svi dogadjaji u JavaScriptu se izvršavaju asinhrono, jer pri kompajliranju koda JS engine stavlja callback funkcije vezane za dogadjaje sa strane i tako ne blokira izvršavanje ostalog koda.

Primer

U ovom primeru pri svakom kliku mišem se “okinu” tri dogadjaja i aktiviraju se tri callback funkcije koje ne blokiraju izvršavanje Javascript koda već se prosledjuju u “queue” gde čekaju da se isprazni stack.

asinhro event

Pogledajte animaciju ovog primera ovde (Savet: kliknite na ikonicu dva ukrštena čekića u gornjem levom uglu aplikacije da promenite brzinu izvršavanja koda).

NAPOMENA:
Ne blokirajte event loop!!! Ceo princip asinhronog rada JavaScript-a i Runtime Environment-a se zasniva na tome da se delovi koda prosledjuju iz “queue” na stack sa Event Loop-om, medjutim ukoliko je stack stalno zauzet (npr. neki veliki while loop, ili neki zahtevan rendering…), tada nismo u mogućnosti da izvršimo asinhronu radnju koja čeka u “queue”.


JS snippets u radu sa DOM-om

Uvod

U ovome članku sam pokušao da sakupim JavaScript isečke koda (eng. code snippets), koji mogu biti korisni u svakodnevnom radu sa DOM-om. Skoro svi snippet-i su napisani u dve verzije, koristeći samo plain JavaScript ili uz pomoć jQuery biblioteke.

js iseci koda - code snippets

Document Ready

U sledećim primerima je prikazan “event listener” koji čeka trenutak kada je DOM učitan da bi JavScript mogao sa njim da manipuliše. Isto bi se dobilo kada bi JavaScript kod stavili na kraj body-ja tj. ispred samog zatvarajućeg taga “body”.



Document Load

Dogadjaj load se “okida” tek kad se učita cela stranica sa svim CSS stilovima, slikama



Continue reading…


(Ne)moguće greške u JavaScript-u

Uvod

javascript error

JavaScript je specifičan programski jezik i u poredjenju sa drugim jezicima ponekad probleme rešava na drugačiji način od očekivanog, ali to ne znači da je taj način i pogrešan. Iza svake “čudne” odluke vezane za sintaksu jezika stoji dobar razlog zbog čega je tim koji radi na razvoju JavaScript-a baš nju izabrao. Da bi se razumele specifičnosti jezika potrebno je temeljno proučiti sintaksu i principe rada jezika. Postoji jedan manji broj nelogičnosti koje i dalje ne mogu tako lako da “svarim”, ali niko nije savršen pa tako ni JavaScript. Smatra se da programeri koji dodju u kontakt sa JavaScript-om kao drugim jezikom imaju malo više problema da se prilagode, jer očekuju iste principe kao u svom omiljenom programskom jeziku ali i ih ovde ne nalaze. U ovom članku sam sakupio potencijalne (ne)iznudjene greške koje može da napravi običan JavaScript smrtnik. Članak će se redovno ažurirati kako budem grešio 🙂

Continue reading…


Pregled objekata ugradjenih u okruženje (Browser & node)

Uvod

js this

JavaScript je skriptni jezik “smešten” u neki kontejner koji mu omogućava rad (pročitaj više o JS okruženju u članku JS okruženje). Taj kontejner (browser ili node.js) sadrži objekte koji omogućavaju komunikaciju JavaScript-a sa spoljnim svetom. Ti objekti su poznati pod nazivom “external API” ili “Web API”. Spisak svih Web API-ja možete pogledati na stranici https://developer.mozilla.org/en-US/docs/Web/API. U naredno delu sam pokušao da okupim na jednom mestu najčešće korišćene objekte i njihove metode i svojsva.

Continue reading…