Jelajahi Sumber

HW_18 (rest_grafql) done

Graf15 2 tahun lalu
induk
melakukan
a9abbdf5b3

+ 20 - 0
js/js_18_rest_grafql/index.html

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <link rel="stylesheet" href="style.css">
+  <title>Document</title>
+
+</head>
+
+<body>
+  <div id="svetofor"></div>
+  <div id="padestrianSvetofor"></div>
+  <div id="padestrianSvetoforButton">BUTTON</div>
+  <script src="index.js"></script>
+</body>
+
+</html>

+ 267 - 0
js/js_18_rest_grafql/index.js

@@ -0,0 +1,267 @@
+/*Светофор
+Используя асинхронную функцию и бесконечный цикл, просимулируйте светофор:
+
+Для отображения включения того или иного света используйте один или три DOM-элемента.
+Stage 2
+Сделайте trafficLight более универсальной - добавьте в параметры DOM-элемент для отображения, а так же время работы каждого цвета
+*/
+
+const delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms))
+
+
+async function trafficLight(element, ms){
+    while (true){
+        //включаем зеленый
+        element.className = "svetoforGreen"
+        await delay(ms)
+        //включаем желтый
+        element.className = "svetoforYellow"
+        await delay(ms)
+        //включаем красный
+        element.className = "svetoforRed"
+        await delay(ms)
+    }
+}
+
+trafficLight(svetofor, 3000)
+
+/*PedestrianTrafficLight
+Напишите упрощенный светофор для пешеходов
+Stage 2
+Используя Promise.race, domEventPromise и кнопку в DOM сделайте пешеходный светофор с кнопкой, который так же переключается по времени периодически.
+Stage 3
+Не давайте возможности пешеходам сильно наглеть - предусмотрите задержку, после которой будет работать кнопка.*/
+{
+    function domEventPromise(element, eventName) {
+        function executor(resolve) {
+            //happy hacking
+            function myEvent(event) {
+                console.log('click')
+                element.removeEventListener(eventName, myEvent)
+                resolve(event)
+
+            }
+
+
+            element.addEventListener(eventName, myEvent)
+
+        }
+        return new Promise(executor)
+    }
+
+
+
+    async function PedestrianTrafficLight(element, ms) {
+        while (true) {
+            //включаем зеленый
+            element.className = "svetoforGreen"
+            await delay(ms)
+
+            //включаем красный
+
+            element.className = "svetoforRed"
+            await delay(2000)
+            await Promise.race([
+                delay(ms - 2000),
+                domEventPromise(padestrianSvetoforButton, 'click')
+            ])
+        }
+    }
+
+    PedestrianTrafficLight(padestrianSvetofor, 8000)
+
+
+}
+
+/* speedtest
+Написать асинхронную функцию
+
+async function speedtest(getPromise, count,parallel=1){
+....
+    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)
+
+где:
+count - количество повторов
+parallel - количество одновременных запросов/промисов в одном повторе
+getPromise - функция, которая умеет вернуть нужный Вам промис для тестирования скорости его работы
+которая будет в цикле count раз создавать parallel промисов с помощью переданной функции getPromise, дожидаться выполнения всех parallel промисов, после чего цикл повторяется.
+Замерить время общее время выполнения, и вычислить:
+duration, общую длительность работы цикла
+parallelDuration, среднее время обработки запроса параллельно (за какое время исполнилось parallel*count промисов),
+paralledSpeed, скорость в запросах в миллисекунду
+queryDuration, реальное среднее время запроса (отталкиваясь от count и времени работы цикла).
+querySpeed, реальное средняя скорость запроса
+Эти переменные вернуть в одном объекте-результате (см. заготовку выше)
+Для отладки попробуйте на delay (пример выше есть, реальное время будет отличаться на единицы-десятки миллисекунд). Потом можете попробовать на swapi.dev. Не создавайте чрезмерно много параллельных запросов.
+*/
+{
+    function makeProfileTimer() {
+        const t0 = performance.now()
+        return () => {
+            const t1 = performance.now()
+            return t1 - t0
+        }
+    }
+
+    /*var timer = makeProfileTimer()
+    alert('Замеряем время работы этого alert')
+    alert(timer())*/
+
+
+
+
+
+    async function speedtest(getPromise, count, parallel = 1) {
+
+        let durationStart = makeProfileTimer() //засекаем время старта всего цикла (duration)
+
+        for (let i = 0; i < count; i++) { // в этом цикле задаем количество повторов count
+            let parallelArr = [] //тут будут храниться промисы
+            for (let p = 0; p < parallel; p++) { //добавляем нужное количество промисов в массив для запуска теста с параллельно запущеніми промисами
+                parallelArr.push(getPromise())
+            }
+
+            await Promise.all(parallelArr) // тут запускаем все промисы из одной паралели и ждем пока зарезолвятся все
+        }
+
+        let duration = durationStart() //записываем в duration разницу между точкой старта перед циклом и этой точкой 
+        let parallelDuration = duration / (parallel * count)
+        let querySpeed = (parallel * count) / duration
+        let queryDuration = duration / count
+        let parallelSpeed = (parallel * count) / duration
+
+        ////
+        return {
+            duration,
+            querySpeed, //средняя скорость одного запроса
+            queryDuration, //
+            parallelSpeed,
+            parallelDuration
+        }
+    }
+
+    speedtest(() => fetch('http://swapi.dev/api/people/1').then(res => res.json()), 10, 5).then(x => console.log(x))
+}
+  /*gql
+Напишите функцию gql, которая осуществляет GraphQL запрос. Функция принимает три параметра:
+Эндпоинт - адрес сервера. Например "http://shop-roles.node.ed.asmer.org.ua/graphql"
+Текст запроса (query). Например:
+query cats($q: String){
+    CategoryFind(query: $q){
+        _id name
+    }
+}
+
+Параметры(переменные) (variables) запроса объектом. Например:
+{
+    q: "[{}]"
+}
+Функция должна возвращать промис, созданный fetch со следующими настройками:
+Метод POST
+Заголовки:
+Content-Type - application/json
+Accept- application/json
+Тело - JSON, объект с двумя ключами - query (текст запроса) и variables
+Проверьте вашу функцию:*/
+{
+    ;(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)
+    })()
+
+
+    async function gql(endpoint, myquery, variables) {
+        let result = await fetch(endpoint, {
+            method: 'POST',
+            headers: {
+                'Content-Type': 'application/json;charset=utf-8',
+                'Accept': 'application/json'
+            },
+            body: JSON.stringify({
+                query: myquery,
+                variables: variables
+            })
+        }).then(res => res.json())
+
+        return result
+
+    }
+}
+
+/*jwtDecode
+Напишете функцию jwtDecode, которая принимает единственный параметр token и возвращает информацию из переданного JWT токена.
+Алгоритм раскодирования:
+Разбить токен на три части. Разделитель - . (точка)
+Выделить среднюю часть.
+Используя функцию atob раскодировать среднюю часть из кодировки Base64, получив JSON
+Раскодировать JSON
+Вернуть раскодированные данные из JSON
+Учтите, что в качестве токена может быть передана какая-то дичь. В таком случае раскодировка не получится, и функция:
+Не должна сыпать красными матюками (ошибками) в консоль
+Должна просто вернуть undefined*/
+
+{
+    const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOnsiaWQiOiI2MzIyMDVhZWI3NGUxZjVmMmVjMWEzMjAiLCJsb2dpbiI6InRlc3Q0NTciLCJhY2wiOlsiNjMyMjA1YWViNzRlMWY1ZjJlYzFhMzIwIiwidXNlciJdfSwiaWF0IjoxNjY4MjcyMTYzfQ.rxV1ki9G6LjT2IPWcqkMeTi_1K9sb3Si8vLB6UDAGdw"
+console.log(jwtDecode(token)) 
+//{
+//  "sub": {
+//    "id": "632205aeb74e1f5f2ec1a320",
+//    "login": "test457",
+//    "acl": [
+//      "632205aeb74e1f5f2ec1a320",
+//      "user"
+//    ]
+//  },
+//  "iat": 1668272163
+//}
+
+function jwtDecode(token) {
+    let result;
+    try {
+      let secondPartToken = token.split('.')[1];
+      result = JSON.parse(atob(secondPartToken));
+    } catch (e) {
+    }
+
+    return result;
+  }
+
+try {
+    console.log(jwtDecode())         //undefined
+    console.log(jwtDecode("дичь"))   //undefined
+    console.log(jwtDecode("ey.ey.ey"))   //undefined
+    
+    console.log('до сюда доработало, а значит jwtDecode не матерился в консоль красным цветом')
+}
+finally{
+    console.log('ДЗ, видимо, окончено')
+}
+}

+ 38 - 0
js/js_18_rest_grafql/style.css

@@ -0,0 +1,38 @@
+*,
+*:before,
+*:after {
+  box-sizing: border-box;
+}
+
+body {
+    margin: 0;
+    height: 100vh;
+    background-color: darkgrey;
+    padding: 10px;
+
+}
+
+#svetofor, #padestrianSvetofor, #padestrianSvetoforButton{
+  width: 100px;
+  height: 100px;
+  border-radius: 50%;
+  margin: 20px;
+  border: 2px solid black;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  color: green;
+  font-weight: bolder;
+}
+
+.svetoforRed {
+  background-color: red;
+}
+
+.svetoforYellow {
+  background-color: yellow;
+}
+
+.svetoforGreen {
+  background-color: green;
+}