Nový Javascript 2

Promise

Stiahnite si kód:

Zadanie

Máme funkciu na načítanie ponúk zo serveru pomocou ajaxu a máme funkciu na animované zobrazenie takto získaných výsledkov.

 

Chceme načítať zoznam inzerátov,

následne ich vypísať

a po vykreslení výsledkov zobraziť tlačidlo.

 

Počas načítavania sa bude zobrazovať loader "obrázok".

Výsledok

displayLoader();

loadAjax(
    'https://api.profesia.sk/offers',
    function (payload) {
        hideLoader();

        displayOffers(payload.offers, function () {
            showButton();
        });
    },
    function (errorMessage) {
        throw errorMessage;
    }
);

Promise

Prísľub o tom, že v budúcnosti: "vrátim hodnotu alebo vyhlásim chybu"

Promise

Promise je objekt

Reprezentuje dokončenie alebo zlyhanie (zväčša) asynchrónnej operácie

A návratovú hodnotu z tejto operácie

Promise

const promise = new Promise(
    function (resolve, reject) {
        // - spustenie asynchrónnej operácie
        // - pri úspechu sa zavolá resolve()
        //   s prípadnými parametrami
        // - pri neúspechu sa zavolá reject()
        //   s dôvodom neúspechu ako parametrom
    }
);
const promise = new Promise(
    executor
);

Promise

const promise = new Promise(
    function (resolve, reject) {
        setTimeout(
            function () {
                console.log('Úspech');

                resolve({foo: bar});
            },
            3000
        );
    }
);

Promise

new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();

    xhr.open("GET", url);

    xhr.onload = () => resolve(xhr.responseText);
    xhr.onerror = () => reject(xhr.statusText);

    xhr.send();
});

Promise

const promise = new Promise(/* ... */);

promise.then(
    onSuccess,
    onReject
);

Promise

const promise = new Promise(/* ... */);

promise.then(
    function (data) {
        console.log('This is my happy day');
        console.log(data);
    },
    function (rejectReason) {
        console.error(rejectReason);
    }
);

Promise

Prísľuby a garancie

  • viacnásobným volaním then viete pridávať viacero callbackov
  • callbacky sa nikdy nezavolajú pred skončením aktuálnej event loop iterácie
  • zavolajú sa aj callbacky pridané po ukončení asynchrónnej operácie
  • callbacky sa zavolajú v poradí, v akom boli pridávané

Promise

Chaining

Návratová hodnota callbacku sa interne obalí do promise (ak už ním nie je).

Takýto promise sa použije ako návratová hodnota z funkcie then

Vďaka tomuto môžete volania then reťaziť

Promise

const promise = new Promise(/* ... */);

promise
    .then((jsonString) => JSON.parse(jsonString))
    .then((data) => {
        return (data.formatVersion === '1')
           ? data.offers : 
           : data.payload.offers;
    })
    .then((offers) => {
        console.log(offers);
    });

Promise

const promise = new Promise(/* ... */);

promise
    .then((jsonString) => JSON.parse(jsonString))
    .then((data) => {
        if (data.formatVersion === '1') {
            throw 'Unsupported version';
        }

        return data.offers;
    })
    .then((offers) => {
        console.log(offers);
    })
    .catch(errorMessage) {
        console.error(errorMessage);
    });

Ak vznikne výnimka, je možné ju odchytit pomocou metódy catch

Promise

Úloha

Prepíšte príklad z úvodu za použitia promise

Promise

Výsledok

const loadAjax = (url) => {
    return new Promise((resolve, reject) => {
        setTimeout(
            () => {
                const resultData = {/* ... */};

                if (resultData.error === 0) {
                    resolve(resultData.payload);
                } else {
                    reject(
                        `Chyba na serveri:
                         ${resultData.error}`
                    );
                }
            },
            1500
        );
    };
};

Promise

Výsledok

const displayOffers = (offers) => {
    return new Promise((resolve, reject) => {
        const timeout = 1000;

        offers.map(/* ... */);

        setTimeout(
            () => {
                resolve();
            },
            timeout * offers.length
        );
    };
};

Promise

Výsledok

loadAjax('https://api.profesia.sk/offers')
    .then(
        (payload) => {
            hideLoader();

            return payload.offers;
        },
        (rejectReason) => {
            throw rejectReason;
        }
    )
    .then((offers) => displayOffers(offers))
    .then(() => showButton())
    .catch((errorMessage) => {
        console.error(errorMessage)
    });

Promise

Promise

Výhody používania Promise

Redukcia tzv. Callback Hell (Pyramid of Doom)

Promise

Výhody používania Promise

Príprava na async-await

Možnosť registrovať viac callbackov k udalosti

Callbacky sa dajú registrovať dodatočne

Odchytávanie chýb pre celý chain