Загрузка данных


<!DOCTYPE html>
<html lang="ru">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Работа Promise</title>

    <style>
        * {
            box-sizing: border-box;
        }

        body {
            margin: 0;
            min-height: 100vh;
            padding: 35px;
            font-family: Arial, sans-serif;
            background-color: #f3f1f1;
            color: #222;
        }

        .container {
            width: min(1100px, 100%);
            margin: 0 auto;
        }

        h1 {
            margin: 0 0 25px;
            text-align: center;
            font-size: 34px;
        }

        /* Верхний блок */

        .explanation {
            padding: 28px;
            margin-bottom: 35px;
            background-color: rgb(190, 193, 193);
            border-radius: 16px;
            box-shadow: 0 8px 25px rgba(0, 0, 0, 0.10);
        }

        .explanation h2 {
            margin: 0 0 10px;
        }

        .explanation > p {
            margin: 0;
            line-height: 1.5;
            color: #3d3d3d;
        }

        /* Состояния Promise */

        .states {
            display: flex;
            gap: 15px;
            margin-top: 25px;
        }

        .state {
            flex: 1;
            padding: 24px;
            text-align: center;
            border-radius: 12px;
            color: #1d1d1d;
            transition: transform 0.2s ease, box-shadow 0.2s ease;
        }

        .state:hover {
            transform: translateY(-3px);
            box-shadow: 0 8px 18px rgba(0, 0, 0, 0.14);
        }

        .state h3 {
            margin: 0 0 8px;
            font-size: 20px;
        }

        .state p {
            margin: 0;
            color: #252525;
        }

        .pending {
            background-color: rgb(129, 86, 86);
        }

        .fulfilled {
            background-color: #a76b73;
        }

        .rejected {
            background-color: rgb(136, 60, 66);
        }

        /* Окна демонстрации */

        .demo-window {
            padding: 26px;
            margin-bottom: 30px;
            background-color: #e8e5e5;
            border: 1px solid rgba(129, 86, 86, 0.22);
            border-radius: 18px;
            box-shadow: 0 12px 35px rgba(0, 0, 0, 0.10);
        }

        .demo-header {
            margin-bottom: 18px;
            padding-bottom: 16px;
            border-bottom: 1px solid rgba(129, 86, 86, 0.20);
        }

        .demo-header h2 {
            margin: 0;
            font-size: 23px;
        }

        /* Визуализация Promise */

        .promise-visual {
            display: flex;
            flex-direction: column;
            gap: 10px;
            margin-bottom: 18px;
        }

        .promise-item {
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 14px 18px;
            background-color: #d8d4d4;
            border-radius: 10px;
            font-size: 15px;
            font-weight: 600;
            transition: background-color 0.3s ease;
        }

        .promise-item.pending-item {
            background-color: rgb(129, 86, 86);
        }

        .promise-item.fulfilled-item {
            background-color: #a76b73;
        }

        .promise-item.rejected-item {
            background-color: rgb(136, 60, 66);
        }

        .promise-state {
            padding: 5px 10px;
            background-color: rgba(255, 255, 255, 0.25);
            border-radius: 15px;
            font-size: 13px;
        }

        /* Консоли */

        .console {
            height: 220px;
            padding: 22px;
            overflow-y: auto;
            background-color: #252525;
            color: white;
            border-radius: 12px;
            font-family: Consolas, monospace;
            font-size: 15px;
            line-height: 1.6;
            box-shadow:
                inset 0 0 0 1px rgba(255, 255, 255, 0.04),
                0 8px 20px rgba(0, 0, 0, 0.14);
        }

        .console::-webkit-scrollbar {
            width: 8px;
        }

        .console::-webkit-scrollbar-thumb {
            background-color: rgb(129, 86, 86);
            border-radius: 10px;
        }

        /* Кнопки */

        .demo-area {
            display: flex;
            gap: 12px;
            margin-top: 18px;
            flex-wrap: wrap;
        }

        button {
            padding: 12px 24px;
            border: none;
            outline: none;
            border-radius: 9px;
            font-size: 15px;
            font-weight: 600;
            cursor: pointer;
            user-select: none;

            transition:
                transform 0.15s ease,
                background-color 0.25s ease,
                box-shadow 0.25s ease;
        }

        #createPromise,
        #runAsync {
            background-color: #a76b73;
            color: #1d1d1d;
            box-shadow: 0 5px 14px rgba(129, 86, 86, 0.25);
        }

        #createPromise:hover,
        #runAsync:hover {
            background-color: rgb(187, 102, 102);
            transform: translateY(-2px);
            box-shadow: 0 8px 18px rgba(129, 86, 86, 0.35);
        }

        #clearConsole,
        #clearAsync {
            background-color: #d8d4d4;
            color: #222;
        }

        #clearConsole:hover,
        #clearAsync:hover {
            background-color: rgb(129, 86, 86);
            transform: translateY(-2px);
            box-shadow: 0 7px 16px rgba(129, 86, 86, 0.25);
        }

        button:active {
            transform: translateY(1px) scale(0.97);
        }

        /* Логи */

        .log-entry {
            margin: 6px 0;
        }

        .info {
            color: #d9b6b9;
        }

        .success {
            color: #d58b91;
        }

        .error {
            color: #a76b73;
        }

        @media (max-width: 700px) {
            body {
                padding: 20px;
            }

            .states,
            .demo-area {
                flex-direction: column;
            }

            button {
                width: 100%;
            }
        }
    </style>
</head>

<body>

<div class="container">

    <h1>Promise в JS</h1>

    <!-- Что такое Promise -->

    <div class="explanation">

        <h2>Что такое Promise?</h2>

        <p>
            Promise (с англ. «обещание») в JavaScript —
            это специальный объект, который представляет
            результат асинхронной операции.
        </p>

        <div class="states">

            <div class="state pending">
                <h3>Pending</h3>
                <p>Ожидание</p>
            </div>

            <div class="state fulfilled">
                <h3>Fulfilled</h3>
                <p>Исполнено</p>
            </div>

            <div class="state rejected">
                <h3>Rejected</h3>
                <p>Отклонено</p>
            </div>

        </div>

    </div>


    <!-- ПЕРВАЯ ДЕМКА PROMISE -->

    <div class="demo-window">

        <div class="demo-header">
            <h2>Демо работы Promise</h2>
        </div>

        <div id="promiseVisual" class="promise-visual"></div>

        <div id="console" class="console"></div>

        <div class="demo-area">

            <button id="createPromise">
                Создать Promise
            </button>

            <button id="clearConsole">
                Очистить консоль
            </button>

        </div>

    </div>


    <!-- ВТОРАЯ ДЕМКА ASYNC/AWAIT -->

    <div class="demo-window">

        <div class="demo-header">
            <h2>Пример с async/await</h2>
        </div>

        <div id="asyncConsole" class="console"></div>

        <div class="demo-area">

            <button id="runAsync">
                Запустить async/await
            </button>

            <button id="clearAsync">
                Очистить консоль
            </button>

        </div>

    </div>

</div>


<script>

    /* =================================
       ПЕРВАЯ ДЕМКА — PROMISE
    ================================= */

    const consoleBlock = document.getElementById('console');
    const promiseVisual = document.getElementById('promiseVisual');

    let promiseCounter = 0;


    function addLog(message, type = 'info') {

        const logEntry = document.createElement('div');

        logEntry.className = `log-entry ${type}`;
        logEntry.textContent = `> ${message}`;

        consoleBlock.appendChild(logEntry);
        consoleBlock.scrollTop = consoleBlock.scrollHeight;
    }


    document
        .getElementById('createPromise')
        .addEventListener('click', function () {

            promiseCounter++;

            const currentPromise = promiseCounter;

            const promiseItem =
                document.createElement('div');

            promiseItem.className =
                'promise-item pending-item';

            promiseItem.innerHTML = `
                <span>Promise #${currentPromise}</span>
                <span class="promise-state">Pending</span>
            `;

            promiseVisual.appendChild(promiseItem);

            const stateText =
                promiseItem.querySelector('.promise-state');


            addLog(
                `Promise #${currentPromise} created`
            );

            addLog(
                `Promise #${currentPromise}: Pending`
            );


            const promise =
                new Promise((resolve, reject) => {

                    setTimeout(() => {

                        const success =
                            Math.random() > 0.5;

                        if (success) {

                            resolve('Success');

                        } else {

                            reject(
                                'Promise failed with error'
                            );

                        }

                    }, 2000);

                });


            promise

                .then(function (result) {

                    promiseItem.className =
                        'promise-item fulfilled-item';

                    stateText.textContent =
                        'Fulfilled';

                    addLog(
                        `Promise #${currentPromise}: Fulfilled`,
                        'success'
                    );

                    addLog(
                        result,
                        'success'
                    );

                })

                .catch(function (error) {

                    promiseItem.className =
                        'promise-item rejected-item';

                    stateText.textContent =
                        'Rejected';

                    addLog(
                        `Promise #${currentPromise}: Rejected`,
                        'error'
                    );

                    addLog(
                        error,
                        'error'
                    );

                });

        });


    document
        .getElementById('clearConsole')
        .addEventListener('click', function () {

            consoleBlock.innerHTML = '';
            promiseVisual.innerHTML = '';
            promiseCounter = 0;

        });



    /* =================================
       ВТОРАЯ ДЕМКА — ASYNC / AWAIT
    ================================= */


    function createAsyncPromise() {

        return new Promise((resolve) => {

            setTimeout(() => {

                resolve(
                    'Данные успешно получены'
                );

            }, 2000);

        });

    }


    function logAsync(message, type = 'info') {

        const asyncConsole =
            document.getElementById('asyncConsole');

        const logEntry =
            document.createElement('div');

        logEntry.className =
            `log-entry ${type}`;

        logEntry.textContent =
            `> ${message}`;

        asyncConsole.appendChild(logEntry);

        asyncConsole.scrollTop =
            asyncConsole.scrollHeight;
    }


    async function runAsyncExample() {

        const asyncConsole =
            document.getElementById('asyncConsole');

        asyncConsole.innerHTML = '';


        logAsync(
            'Начало выполнения'
        );

        logAsync(
            'Ожидаем данные...'
        );


        const result =
            await createAsyncPromise();


        logAsync(
            result,
            'success'
        );

        logAsync(
            'Выполнение завершено',
            'success'
        );

    }


    document
        .getElementById('runAsync')
        .addEventListener('click', function () {

            runAsyncExample();

        });


    document
        .getElementById('clearAsync')
        .addEventListener('click', function () {

            document
                .getElementById('asyncConsole')
                .innerHTML = '';

        });

</script>

</body>
</html>