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


<!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, transform 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,
        #runSuccess {
            background-color: #a76b73;
            color: #1d1d1d;
            box-shadow: 0 5px 14px rgba(129, 86, 86, 0.25);
        }

        #runError {
            background-color: rgb(136, 60, 66);
            color: #1d1d1d;
            box-shadow: 0 5px 14px rgba(129, 86, 86, 0.25);
        }

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

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

        #clearConsole:hover,
        #clearConsole2: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>

    <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>


    <!-- Первая демонстрация -->

    <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>


    <!-- Вторая демонстрация -->

    <div class="demo-window">
        <div class="demo-header">
            <h2>Basic Promise</h2>
        </div>

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

        <div class="demo-area">
            <button id="runSuccess">Запустить успешно</button>
            <button id="runError">Запустить с ошибкой</button>
            <button id="clearConsole2">Очистить консоль</button>
        </div>
    </div>

</div>


<script>

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

    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;
    });



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

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

        const consoleElement = document.getElementById('basicConsole');
        const logEntry = document.createElement('div');

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

        logEntry.textContent =
            `> ${new Date().toLocaleTimeString()}: ${message}`;

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


    function clearBasicConsole() {
        document.getElementById('basicConsole').innerHTML = '';
    }


    function createBasicPromise(success = true) {

        return new Promise((resolve, reject) => {

            setTimeout(() => {

                if (success) {
                    resolve('Data is loaded');
                } else {
                    reject('Data loading error');
                }

            }, 2000);

        });
    }


    function runBasicPromise(success) {

        clearBasicConsole();

        logToConsole(
            'Basic Promise is creating...',
            'info'
        );


        createBasicPromise(success)

            .then(function (result) {
                logToConsole(result, 'success');
            })

            .catch(function (error) {
                logToConsole(error, 'error');
            });
    }


    document.getElementById('runSuccess').addEventListener('click', function () {
        runBasicPromise(true);
    });


    document.getElementById('runError').addEventListener('click', function () {
        runBasicPromise(false);
    });


    document.getElementById('clearConsole2').addEventListener('click', function () {
        clearBasicConsole();
    });

</script>

</body>
</html>