hw20.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. const delaySec = (sec) =>
  2. new Promise((ok) => setTimeout(() => ok(sec), sec * 1000));
  3. async function trafficLight(
  4. domElement,
  5. { redSec = 5, yellowSec = 2, greenSec = 3 } = {}
  6. ) {
  7. while (true) {
  8. domElement.children[2].style.background = "green";
  9. await delaySec(greenSec);
  10. domElement.children[2].style.background = "";
  11. domElement.children[1].style.background = "yellow";
  12. await delaySec(yellowSec);
  13. domElement.children[1].style.background = "";
  14. domElement.children[0].style.background = "red";
  15. await delaySec(redSec - 1);
  16. domElement.children[1].style.background = "yellow";
  17. await delaySec(1);
  18. domElement.children[0].style.background = "";
  19. domElement.children[1].style.background = "";
  20. }
  21. }
  22. trafficLight(lights3, { greenSec: 5 });
  23. //
  24. // domEventPromise
  25. // Реализуйте промисифицированную функцию, которая резолвит промис по событию в DOM:
  26. // domEventPromise(knopka, 'click').then( e => console.log('event click happens', e))
  27. // Функция должна:
  28. // используя addEventListener повесить свой обработчик события на DOM element событие eventName
  29. // по событию зарезолвить промис отдав в качестве результата объект события
  30. // убрать обработчик с DOM-элемента, используя removeEventListener
  31. let domEventPromise = (domElement, eventName) =>
  32. new Promise((resolve) => {
  33. let res = function (e) {
  34. resolve(e);
  35. domElement.removeEventListener(eventName, res);
  36. console.log("domEventPromise - done");
  37. };
  38. domElement.addEventListener(eventName, res);
  39. });
  40. knopka2.onclick = () =>
  41. domEventPromise(knopka, "click").then((e) =>
  42. console.log("event click happens", e)
  43. );
  44. //
  45. // PedestrianTrafficLight
  46. // Напишите упрощенный светофор для пешеходов
  47. function innerTimer(domElement, sec) {
  48. for (let i = sec; i > 0; i--) {
  49. setTimeout(() => (domElement.innerText = i), (sec - i) * 1000);
  50. }
  51. setTimeout(() => (domElement.innerText = ""), sec * 1000);
  52. }
  53. async function pedestrianTrafficLight(
  54. domElement,
  55. { redSec = 10, greenSec = 3 } = {}
  56. ) {
  57. domElement.children[1].style.background = "lightgreen";
  58. innerTimer(domElement.children[1], greenSec);
  59. await delaySec(greenSec);
  60. domElement.children[1].style.background = "";
  61. domElement.children[0].style.background = "red";
  62. innerTimer(domElement.children[0], redSec);
  63. await delaySec(redSec);
  64. domElement.children[0].style.background = "";
  65. }
  66. async function pedestrianManage(domElement) {
  67. while (true) {
  68. await pedestrianTrafficLight(domElement, { redSec: 6 });
  69. }
  70. }
  71. pedestrianManage(lights2);
  72. //
  73. // Stage 2
  74. // Используя Promise.race, domEventPromise и кнопку в DOM сделайте пешеходный светофор с кнопкой,
  75. // который так же переключается по времени периодически.
  76. // Stage 3
  77. // Не давайте возможности пешеходам сильно наглеть - предусмотрите задержку, после которой будет работать кнопка.
  78. //
  79. // Логика работы светофора:
  80. // бОльшую часть времени светофор работает для машин и изредка автоматически включается для пешеходов
  81. // 20 сек - красный (машины едут)
  82. // 5 сек - зеленый(идут пешеходы)
  83. // Для особо спешащих пешеходов есть кнопка, которая позволяет ТОЛЬКО в фазе "красный" переключиться сразу на зеленый
  84. // После этого незапланированного "зеленого" цикла продолжит дорабатывать свое время "красный" цикл.
  85. // но за такую спешку надо платить: 20 секнд после "зеленого" нажать на кнопку будет нельзя а новая фаза "красного"
  86. // начнется без прерывания на зеленый (то есть пропуск "зеленой" фазы, которая должна была бы быть по расписанию)
  87. async function pedestrianManageBtn(domElement) {
  88. //
  89. async function redLite(redTime) {
  90. domElement.children[1].style.background = "";
  91. domElement.children[0].style.background = "red";
  92. innerTimer(domElement.children[0], redTime);
  93. await delaySec(redTime);
  94. // return "red";
  95. }
  96. async function greenLite(greenTime) {
  97. goButton.disabled = true;
  98. domElement.children[0].style.background = "";
  99. domElement.children[1].style.background = "lightgreen";
  100. innerTimer(domElement.children[1], greenTime);
  101. await delaySec(greenTime);
  102. domElement.children[1].style.background = "";
  103. domElement.children[0].style.background = "red";
  104. if (goButton.innerText === "GO") {
  105. goButton.disabled = false;
  106. }
  107. // return "green";
  108. }
  109. let goButtonDelay = 20; // задержка кнопки в секундах - плата за экстренный зеленый
  110. let redDelay = 20; // стандартное время работы красного в секундах
  111. let greenDelay = 5; // стандартное время работы зеленого в секундах
  112. let btn, red, green;
  113. let isGoButtonPressed;
  114. while (true) {
  115. isGoButtonPressed = false;
  116. btn = domEventPromise(goButton, "click");
  117. btn.then(() => {
  118. goButton.disabled = true;
  119. isGoButtonPressed = true;
  120. innerTimer(goButton, goButtonDelay + greenDelay);
  121. setTimeout(() => {
  122. if (domElement.children[1].style.background !== "lightgreen")
  123. goButton.disabled = false;
  124. goButton.innerText = "GO";
  125. }, (goButtonDelay + greenDelay) * 1000);
  126. });
  127. while (!isGoButtonPressed) {
  128. await Promise.race([btn, (red = redLite(redDelay))]).then(
  129. () => (green = greenLite(greenDelay))
  130. );
  131. await Promise.all([red, green]);
  132. console.log("await Promise.all([red, green])");
  133. }
  134. }
  135. // ниже - старый но рабочий вариант
  136. // while (true) {
  137. // await Promise.race([(btn = domEventPromise(goButton, "click")), (red = redLite(20))]).then(() => {
  138. // green = greenLite(5);
  139. // btn.then(() => {
  140. // innerTimer(goButton, 20);
  141. // goButton.disabled = true;
  142. // setTimeout(() => {
  143. // goButton.disabled = false;
  144. // goButton.innerText = "GO";
  145. // }, 20000);
  146. // });
  147. // });
  148. // await Promise.all([red, green]);
  149. // }
  150. }
  151. pedestrianManageBtn(lights2btn);
  152. //
  153. //
  154. // speedtest
  155. // Написать асинхронную функцию
  156. // async function speedtest(getPromise, count,parallel=1){
  157. // ....
  158. // return {
  159. // duration,
  160. // querySpeed, //средняя скорость одного запроса
  161. // queryDuration, //
  162. // parallelSpeed,
  163. // parallelDuration
  164. // }
  165. // }
  166. // speedtest(() => delay(1000), 10, 10 ).then(result => console.log(result))
  167. // // {duration: 10000,
  168. // // querySpeed: 0.001, //1 тысячная запроса за миллисекунду
  169. // // queryDuration: 1000, //1000 миллисекунд на один реальный запрос в среднем
  170. // // parallelSpeed: 0.01 // 100 запросов за 10000 миллисекунд
  171. // // parallelDuration: 100 // 100 запросов за 10000 миллисекунд
  172. // speedtest(() => fetch('http://swapi.dev/api/people/1').then(res => res.json()), 10, 5)
  173. // где:
  174. // count - количество повторов
  175. // parallel - количество одновременных запросов/промисов в одном повторе
  176. // getPromise - функция, которая умеет вернуть нужный Вам промис для тестирования скорости его работы
  177. // которая будет в цикле count раз создавать parallel промисов с помощью переданной функции getPromise,
  178. // дожидаться выполнения всех parallel промисов, после чего цикл повторяется.
  179. // Замерить время общее время выполнения, и вычислить:
  180. // duration, общую длительность работы цикла
  181. // parallelDuration, среднее время обработки запроса параллельно (за какое время исполнилось parallel*count промисов),
  182. // paralledSpeed, скорость в запросах в миллисекунду
  183. // queryDuration, реальное среднее время запроса (отталкиваясь от count и времени работы цикла).
  184. // querySpeed, реальное средняя скорость запроса
  185. // Эти переменные вернуть в одном объекте-результате (см. заготовку выше)
  186. // Для отладки попробуйте на delay (пример выше есть, реальное время будет отличаться на единицы - десятки миллисекунд).
  187. // Потом можете попробовать на swapi.dev.Не создавайте чрезмерно много параллельных запросов.
  188. const delay = (msec) =>
  189. new Promise((resolve) => setTimeout(() => resolve(msec), msec));
  190. let setTimer = function () {
  191. let timeStart = performance.now();
  192. return function () {
  193. return performance.now() - timeStart;
  194. };
  195. };
  196. async function speedtest(getPromise, count = 1, parallel = 1) {
  197. //
  198. let duration, querySpeed, queryDuration, parallelSpeed, parallelDuration;
  199. let promiseArr = [];
  200. duration = setTimer();
  201. for (let iterations = 0; iterations < count; iterations++) {
  202. for (let together = 0; together < parallel; together++)
  203. promiseArr.push(getPromise());
  204. // let timer = setTimer();
  205. await Promise.all(promiseArr);
  206. // timer = timer();
  207. }
  208. duration = duration();
  209. parallelSpeed = (count * parallel) / duration;
  210. parallelDuration = 1 / parallelSpeed;
  211. queryDuration = duration / count;
  212. querySpeed = 1 / queryDuration;
  213. return {
  214. duration,
  215. querySpeed,
  216. queryDuration,
  217. parallelSpeed,
  218. parallelDuration,
  219. };
  220. }
  221. speedtest(() => delay(1000), 10, 10).then((result) =>
  222. console.log(" delay(1000) ", result)
  223. );
  224. speedtest(
  225. () => fetch("http://swapi.dev/api/people/1").then((res) => res.json()),
  226. 10,
  227. 5
  228. ).then((result) => console.log(" swapi.dev ", result));