// Светофор // Используя асинхронную функцию и бесконечный цикл, просимулируйте светофор: // Для отображения включения того или иного света используйте один или три DOM-элемента. // Stage 2 // Сделайте trafficLight более универсальной - добавьте в параметры DOM-элемент для отображения, а так же время // работы каждого цвета traffic_light: { const delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms)); let trafficLightEl = document.createElement('div'); document.body.append(trafficLightEl); trafficLightEl.classList.add('traffic-light'); let red = document.createElement('div'); trafficLightEl.append(red); red.classList.add('cell'); let yellow = document.createElement('div'); trafficLightEl.append(yellow); yellow.classList.add('cell'); let green = document.createElement('div'); trafficLightEl.append(green); green.classList.add('cell'); async function trafficLight(greenEl, yellowEl, redEl, greenTime, yellowTime, redTime) { while (true) { greenEl.classList.add('green'); await delay(greenTime); greenEl.classList.remove('green'); yellowEl.classList.add('yellow'); await delay(yellowTime); yellowEl.classList.remove('yellow'); redEl.classList.add('red'); await delay(redTime); redEl.classList.remove('red'); } } trafficLight(green, yellow, red, 6000, 1000, 6000); } // PedestrianTrafficLight // Напишите упрощенный светофор для пешеходов // Stage 2 // Используя Promise.race, domEventPromise и кнопку в DOM сделайте пешеходный светофор с кнопкой, который так // же переключается по времени периодически. // Stage 3 // Не давайте возможности пешеходам сильно наглеть - предусмотрите задержку, после которой будет работать // кнопка. pedestrian_traffic_light: { const delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms)); let pedestrianTrafficLightEl = document.createElement('div'); document.body.append(pedestrianTrafficLightEl); pedestrianTrafficLightEl.classList.add('traffic-light'); let red = document.createElement('div'); pedestrianTrafficLightEl.append(red); red.classList.add('cell'); let green = document.createElement('div'); pedestrianTrafficLightEl.append(green); green.classList.add('cell'); let button = document.createElement('button'); button.innerText = 'switch'; document.body.append(button); function domEventPromise(element, eventName) { function executor(resolve) { function myEvent(event) { element.disabled = true; element.removeEventListener(eventName, myEvent); setTimeout(() => resolve(event), 2000); } element.disabled = false; element.addEventListener(eventName, myEvent) } return new Promise(executor); } async function pedestrianTrafficLight(ms) { while (true) { red.classList.add('red'); await Promise.race([ delay(ms), domEventPromise(button, 'click') ]); red.classList.remove('red'); green.classList.add('green'); await delay(ms); green.classList.remove('green'); } } pedestrianTrafficLight(6000); } // speedtest // Написать асинхронную функцию, где: // count - количество повторов // parallel - количество одновременных запросов/промисов в одном повторе // getPromise - функция, которая умеет вернуть нужный Вам промис для тестирования скорости его работы // которая будет в цикле count раз создавать parallel промисов с помощью переданной функции getPromise, // дожидаться выполнения всех parallel промисов, после чего цикл повторяется. // Замерить время общее время выполнения, и вычислить: // duration, общую длительность работы цикла // parallelDuration, среднее время обработки запроса параллельно (за какое время исполнилось parallel*count // промисов), // paralledSpeed, скорость в запросах в миллисекунду // queryDuration, реальное среднее время запроса (отталкиваясь от count и времени работы цикла). // querySpeed, реальное средняя скорость запроса // Эти переменные вернуть в одном объекте-результате (см. заготовку выше) // Для отладки попробуйте на delay (пример выше есть, реальное время будет отличаться на единицы-десятки // миллисекунд). Потом можете попробовать на swapi.dev. Не создавайте чрезмерно много параллельных запросов. speedtest: { const delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms)); function makeProfileTimer() { let t0 = performance.now(); return function () { let t1 = performance.now(); return t1 - t0; } } async function speedtest(getPromise, count, parallel = 1) { let timer = makeProfileTimer(); for (let i = 0; i < count; i++) { let promises = []; for (let j = 0; j < parallel; j++) { promises.push(getPromise()); } console.log(await Promise.all(promises)); } let duration = timer(); let parallelDuration = duration / (count * parallel); let parallelSpeed = 1 / parallelDuration; let queryDuration = duration / count; let querySpeed = 1 / queryDuration; return { duration, querySpeed, //средняя скорость одного запроса queryDuration, // parallelSpeed, parallelDuration } } speedtest(() => delay(1000), 10, 10).then(result => console.log(result)); // {duration: 10000, // querySpeed: 0.001, //1 тысячная запроса за миллисекунду // queryDuration: 1000, //1000 миллисекунд на один реальный запрос в среднем // parallelSpeed: 0.01 // 100 запросов за 10000 миллисекунд // parallelDuration: 100 // 100 запросов за 10000 миллисекунд speedtest(() => fetch('http://swapi.dev/api/people/1').then(res => res.json()), 10, 5).then(result => console.log(result)); } // gql // Напишите функцию gql, которая осуществляет GraphQL запрос. Функция принимает три параметра: // Эндпоинт - адрес сервера. Например "http://shop-roles.node.ed.asmer.org.ua/graphql" // Текст запроса (query). // Параметры(переменные) (variables) запроса объектом // Функция должна возвращать промис, созданный fetch со следующими настройками: // Метод POST // Заголовки: // Content-Type - application/json // Accept- application/json // Тело - JSON, объект с двумя ключами - query (текст запроса) и variables gql: { function gql(endpoint, query, variables) { return fetch(endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: JSON.stringify({ query, variables }), }).then(response => response.json()); } (async () => { const catQuery = `query cats($q: String){ CategoryFind(query: $q){ _id name } }` const cats = await gql("http://shop-roles.node.ed.asmer.org.ua/graphql", catQuery, { q: "[{}]" }) console.log(cats) //список категорий с _id name и всем таким прочим const loginQuery = `query login($login:String, $password:String){ login(login:$login, password:$password) }` const token = await gql("http://shop-roles.node.ed.asmer.org.ua/graphql", loginQuery, { login: "test457", password: "123123" }) console.log(token) })() } // jwtDecode // Напишете функцию jwtDecode, которая принимает единственный параметр token и возвращает информацию из // переданного JWT токена. // Алгоритм раскодирования: // Разбить токен на три части. Разделитель - . (точка) // Выделить среднюю часть. // Используя функцию atob раскодировать среднюю часть из кодировки Base64, получив JSON // Раскодировать JSON // Вернуть раскодированные данные из JSON // Учтите, что в качестве токена может быть передана какая-то дичь. В таком случае раскодировка не получится, // и функция: // Не должна сыпать красными матюками (ошибками) в консоль // Должна просто вернуть undefined jwtDecode: { const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOnsiaWQiOiI2MzIyMDVhZWI3NGUxZjVmMmVjMWEzMjAiLCJsb2dpbiI6InRlc3Q0NTciLCJhY2wiOlsiNjMyMjA1YWViNzRlMWY1ZjJlYzFhMzIwIiwidXNlciJdfSwiaWF0IjoxNjY4MjcyMTYzfQ.rxV1ki9G6LjT2IPWcqkMeTi_1K9sb3Si8vLB6UDAGdw"; function jwtDecode(token) { let result; try { let mediumStr = token.split('.')[1]; result = JSON.parse(atob(mediumStr)); } catch (e) { } return result; } console.log(jwtDecode(token)); //{ // "sub": { // "id": "632205aeb74e1f5f2ec1a320", // "login": "test457", // "acl": [ // "632205aeb74e1f5f2ec1a320", // "user" // ] // }, // "iat": 1668272163 //} try { console.log(jwtDecode()); //undefined console.log(jwtDecode("дичь")); //undefined console.log(jwtDecode("ey.ey.ey")); //undefined console.log('до сюда доработало, а значит jwtDecode не матерился в консоль красным цветом'); } finally { console.log('ДЗ, видимо, окончено'); } }