Увод у промисове у JavaScript-у

Већ знате да коришћење callback-модела асинхроности лако доводи до ситуације callback hell. Стога је у JavaScript уведен нови модел под називом промис (promise). Хајде да проучимо овај модел.

Промис представља објекат, коме се параметром прослеђује функција, унутар које треба сместити наш асинхрони код:

javascriptlet promise = new Promise(function() {
  // асинхрони код
});

Као што видите, записао сам објекат са промисом у променљиву promise. На неком другом месту у коду могу применити на ову променљиву метод then, проследивши у њега функцију са кодом, који треба да буде извршен по завршетку асинхроног кода, написаног приликом креирања овог промиса:

javascriptpromise.then(function() {
  // извршиће се при завршетку асинхроног кода
});

Звучи збуњујуће, па хајде да погледамо пример. Нека имам овакав асинхрони код:

javascriptsetTimeout(function() {
  let result = [1, 2, 3, 4, 5];
}, 3000);

Претпоставимо да желим да за њега решим нашу главну задатак асинхроности: извршити неки код након активирања тајмера. При томе не желим да сместим тај код у сам тајмер и желим да у тај код некако доспе резултат, који сам записао у променљиву result. У принципу, решавали смо овај задатак у претходним лекцијама преко callback-ова и претплата. Хајде сада да видимо како то урадити преко промиса.

За почетак треба да умотамо наш асинхрони код у промис:

javascriptlet promise = new Promise(function() {
  setTimeout(function() {
    let result = [1, 2, 3, 4, 5];
  }, 3000);
});

Овога, међутим, није довољно. Морамо експлицитно навести да се наш асинхрони код завршио. У томе ће нам помоћи специјална функција завршетка, која аутоматски доспева у први параметар функције, ако је наведен:

javascriptlet promise = new Promise(function(resolve) { // наводимо параметар
  setTimeout(function() {
    let result = [1, 2, 3, 4, 5];
  }, 3000);
});

Помоћу функције завршетка можемо експлицитно показати промису да се асинхрони код завршио. За то морамо позвати ову функцију на месту које нам треба:

javascriptlet promise = new Promise(function(resolve) {
  setTimeout(function() {
    let result = [1, 2, 3, 4, 5];
    resolve(); // завршавамо промис
  }, 3000);
});

При томе, ако желимо да проследимо неки резултат асинхроног кода напоље, можемо га проследити параметром нашој функцији завршетка:

javascriptlet promise = new Promise(function(resolve) {
  setTimeout(function() {
    let result = [1, 2, 3, 4, 5];
    resolve(result); // прослеђујемо резултат
  }, 3000);
});

Можемо, наравно, да се ослободимо међупроменљиве:

javascriptlet promise = new Promise(function(resolve) {
  setTimeout(function() {
    resolve([1, 2, 3, 4, 5]);
  }, 3000);
});

Сада на било ком другом месту можемо позвати метод then нашег промиса:

javascriptpromise.then(function() {
  // активираће се по завршетку промиса
});

Резултат рада промиса ће доспети у први параметар функције, ако га желимо навести:

javascriptpromise.then(function(result) {
  console.log(result); // исписаће низ са резултатом
});
Задание 1

Направите промис, унутар кога ће бити кашњење од 5 секунди, након чега промис треба да се изврши, вративши као свој резултат неки текст. Испишите тај текст на екран.