Johdatus Promiseihin JavaScriptissä
Tiedät jo, että callback-mallin käyttö asynkronisuudessa johtaa helposti callback hell -tilanteeseen. Siksi JavaScriptiin otettiin käyttöön uusi malli nimeltään promiset (promise). Opiskellaanpa tätä mallia.
Promise edustaa objektia, jolle parametrina välitetään funktio, jonka sisälle meidän tulee sijoittaa asynkroninen koodimme:
let promise = new Promise(function() {
// asynkroninen koodi
});
Kuten näet, tallensin promise-objektin
muuttujaan promise. Jossain muualla
koodissa voin soveltaa tähän muuttujaan
metodia then, välittämällä sille funktion
koodilla, jonka tulisi suorittua, kun
promisen luonnissa määritelty asynkroninen koodi on valmis:
promise.then(function() {
// suoritetaan, kun asynkroninen koodi on valmis
});
Kuulostaa hämmentävältä, joten katsotaanpa esimerkkiä. Oletetaan, että minulla on seuraava asynkroninen koodi:
setTimeout(function() {
let result = [1, 2, 3, 4, 5];
}, 3000);
Oletetaan, että haluan ratkaista sille asynkronisuuden päätavoitteen:
suorittaa tietty koodi ajastimen laukeamisen jälkeen. Samalla
en halua sijoittaa tätä koodia itse ajastimen sisälle
ja haluan, että tähän koodiin jotenkin pääsee tulos,
jonka määrittelin muuttujassa result.
Periaatteessa olemme ratkaisseet tämän ongelman aiemmissa
oppitunneilla callbackien ja tilausten avulla. Katsotaanpa nyt,
kuinka se tehdään promiseilla.
Aluksi meidän täytyy kääriä asynkroninen koodimme promiseen:
let promise = new Promise(function() {
setTimeout(function() {
let result = [1, 2, 3, 4, 5];
}, 3000);
});
Tämä ei kuitenkaan riitä. Meidän täytyy näyttää selkeästi, että asynkroninen koodimme on päättynyt. Tässä auttaa erityinen valmistumisfunktio, joka automaattisesti tulee funktion ensimmäiseksi parametriksi, jos se on määritelty:
let promise = new Promise(function(resolve) { // määritellään parametri
setTimeout(function() {
let result = [1, 2, 3, 4, 5];
}, 3000);
});
Valmistumisfunktion avulla voimme nimenomaisesti ilmoittaa promiselle, että asynkroninen koodi on valmis. Meidän täytyy kutsua tätä funktiota halutussa kohdassa:
let promise = new Promise(function(resolve) {
setTimeout(function() {
let result = [1, 2, 3, 4, 5];
resolve(); // valmistetaan promise
}, 3000);
});
Samalla, jos haluamme välittää ulkopuolelle jonkin asynkronisen koodin tuloksen, voimme välittää sen parametrina valmistumisfunktiollemme:
let promise = new Promise(function(resolve) {
setTimeout(function() {
let result = [1, 2, 3, 4, 5];
resolve(result); // välitetään tulos
}, 3000);
});
Välimuuttujasta voi tietysti luopua:
let promise = new Promise(function(resolve) {
setTimeout(function() {
resolve([1, 2, 3, 4, 5]);
}, 3000);
});
Nyt missä tahansa muualla voimme kutsua
promisemme metodia then:
promise.then(function() {
// laukeaa promisen valmistuessa
});
Promisen tulos tulee funktion ensimmäiseksi parametriksi, jos haluamme määritellä sen:
promise.then(function(result) {
console.log(result); // tulostaa taulukon tuloksen
});
Tee promise, jonka sisällä on viive
5 sekuntia, minkä jälkeen promisen tulisi
valmistua, palauttaen tuloksenaan jonkin tekstin.
Tulosta tämä teksti näytölle.