HW17.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. // Chat
  2. // Используя функцию jsonPost на адрес http://students.a-level.com.ua:10012 напишите чат-клиент, который:
  3. {// jsonPost function
  4. function jsonPost(url, data) {
  5. return new Promise((resolve, reject) => {
  6. var x = new XMLHttpRequest();
  7. x.onerror = () => reject(new Error('jsonPost failed'))
  8. //x.setRequestHeader('Content-Type', 'application/json');
  9. x.open('POST', url, true);
  10. x.send(JSON.stringify(data))
  11. x.onreadystatechange = () => {
  12. if (x.readyState == XMLHttpRequest.DONE && x.status == 200) {
  13. resolve(JSON.parse(x.responseText))
  14. }
  15. else if (x.status != 200) {
  16. reject(new Error('status is not 200'))
  17. }
  18. }
  19. })
  20. }
  21. // общий div
  22. const allChat = document.createElement('div')
  23. allChat.style.cssText = `
  24. margin: 0 auto;
  25. width: min-content;
  26. padding: 10px;
  27. border: 1px solid #e5e5e5;
  28. border-radius: 10px;
  29. box-shadow: 5px 5px 10px 0px rgb(173 173 173);
  30. `
  31. document.body.append(allChat)
  32. // Stage 1 - работает нормаль, отслеживаем nextMessageId и записываем его в getMessageId
  33. const chatDiv = document.createElement('div')
  34. chatDiv.style.cssText = `
  35. border: 1px solid #e5e5e5;
  36. width: 550px;
  37. padding: 10px;
  38. margin-bottom: 20px;
  39. `
  40. allChat.append(chatDiv)
  41. const nickName = document.createElement('input')
  42. nickName.type = 'text'
  43. nickName.placeholder = 'Введите свой никнейм'
  44. nickName.value = 'Anon'
  45. chatDiv.append(nickName)
  46. let lineBreak = document.createElement('br')
  47. chatDiv.append(lineBreak)
  48. const inputText = document.createElement('textarea')
  49. inputText.maxlength = 500
  50. inputText.required
  51. inputText.style.cssText = `
  52. resize: none;
  53. margin: 20px 0px;
  54. height: 90px;
  55. width: 90%;
  56. `
  57. inputText.placeholder = 'Введите текст сообщения'
  58. inputText.value = 'Hi everyone!'
  59. chatDiv.append(inputText)
  60. lineBreak = document.createElement('br')
  61. chatDiv.append(lineBreak)
  62. const sendBtn = document.createElement('button')
  63. sendBtn.innerText = 'Send'
  64. sendBtn.style.padding = '3px 40px'
  65. chatDiv.append(sendBtn)
  66. // отправка сообщения по нажатию кнопки
  67. let getMessageId = 0
  68. sendBtn.onclick = () => {
  69. async function sendMessage() {
  70. const result = jsonPost('http://students.a-level.com.ua:10012', { func: 'addMessage', nick: `${nickName.value}`, message: inputText.value })
  71. await result.then(res => getMessageId = res.nextMessageId)
  72. console.log(getMessageId)
  73. return result.data
  74. }
  75. sendMessage()
  76. }
  77. // stage2
  78. {
  79. const chat = document.createElement('div')
  80. chat.style.cssText = `
  81. min-height: 500px;
  82. padding: 10px;
  83. height: 60%;
  84. width: 550px;
  85. overflow-y: scroll;
  86. overflow-x: hidden;
  87. `
  88. allChat.append(chat)
  89. async function getAllMessages() {
  90. const result = await jsonPost('http://students.a-level.com.ua:10012', { func: "getMessages", messageId: 0 })
  91. const chat = document.createElement('div')
  92. chat.style.cssText = `
  93. min-height: 500px;
  94. padding: 10px;
  95. height: 60%;
  96. width: 550px;
  97. overflow-y: scroll;
  98. overflow-x: hidden;
  99. `
  100. allChat.append(chat)
  101. for (const message of ((result.data).sort((a, b) => b.timestamp - a.timestamp))) {
  102. const chatBlock = document.createElement('div')
  103. chatBlock.style.cssText = `
  104. border: 1px solid #e5e5e5;
  105. border-radius: 10px;
  106. width: 500px;
  107. padding: 10px;
  108. margin-bottom: 20px;
  109. box-shadow: 5px 5px 10px 0px rgb(173 173 173);
  110. `
  111. chat.append(chatBlock)
  112. for (const [key, value] of Object.entries(message)) {
  113. const messageBlock = document.createElement('p')
  114. messageBlock.style.margin = '5px 0'
  115. messageBlock.innerHTML = `<span style = 'font-weight: 800;'>${key}</span>: ${typeof value === 'string' ? value : new Date(value)}`
  116. chatBlock.append(messageBlock)
  117. }
  118. }
  119. return result.data
  120. }
  121. getAllMessages()
  122. }
  123. // stage3
  124. let getNewMessageId = 0
  125. const chat = document.createElement('div')
  126. chat.style.cssText = `
  127. min-height: 500px;
  128. padding: 10px;
  129. height: 60%;
  130. width: 550px;
  131. overflow-y: scroll;
  132. overflow-x: hidden;
  133. `
  134. allChat.append(chat)
  135. async function getMessages(param) {
  136. const result = await jsonPost('http://students.a-level.com.ua:10012', { func: "getMessages", messageId: param })
  137. for (const message of result.data) {
  138. const chatBlock = document.createElement('div')
  139. chatBlock.style.cssText = `
  140. border: 1px solid #e5e5e5;
  141. border-radius: 10px;
  142. width: 500px;
  143. padding: 10px;
  144. margin-bottom: 20px;
  145. box-shadow: 5px 5px 10px 0px rgb(173 173 173);
  146. `
  147. chat.prepend(chatBlock)
  148. for (const [key, value] of Object.entries(message)) {
  149. const messageBlock = document.createElement('p')
  150. messageBlock.style.margin = '5px 0'
  151. messageBlock.innerHTML = `<span style = 'font-weight: 800;'>${key}</span>: ${typeof value === 'string' ? value : new Date(value)}`
  152. chatBlock.append(messageBlock)
  153. }
  154. }
  155. getNewMessageId = result.nextMessageId
  156. return result.data
  157. }
  158. getMessages(getNewMessageId)
  159. // stage 4
  160. const intervalId = setInterval(() => getMessages(getNewMessageId), 4000)
  161. // stage 5
  162. {
  163. function jsonPost(url, data) {
  164. return new Promise((resolve, reject) => {
  165. var x = new XMLHttpRequest();
  166. x.onerror = () => reject(new Error('jsonPost failed'))
  167. //x.setRequestHeader('Content-Type', 'application/json');
  168. x.open('POST', url, true);
  169. x.send(JSON.stringify(data))
  170. x.onreadystatechange = () => {
  171. if (x.readyState == XMLHttpRequest.DONE && x.status == 200) {
  172. resolve(JSON.parse(x.responseText))
  173. }
  174. else if (x.status != 200) {
  175. reject(new Error('status is not 200'))
  176. }
  177. }
  178. })
  179. }
  180. // общий div
  181. const allChat = document.createElement('div')
  182. allChat.style.cssText = `
  183. margin: 0 auto;
  184. width: min-content;
  185. padding: 10px;
  186. border: 1px solid #e5e5e5;
  187. border-radius: 10px;
  188. box-shadow: 5px 5px 10px 0px rgb(173 173 173);
  189. `
  190. document.body.append(allChat)
  191. const chatDiv = document.createElement('div')
  192. chatDiv.style.cssText = `
  193. border: 1px solid #e5e5e5;
  194. width: 550px;
  195. padding: 10px;
  196. margin-bottom: 20px;
  197. `
  198. allChat.append(chatDiv)
  199. const nickName = document.createElement('input')
  200. nickName.type = 'text'
  201. nickName.placeholder = 'Введите свой никнейм'
  202. nickName.value = 'Anon'
  203. chatDiv.append(nickName)
  204. let lineBreak = document.createElement('br')
  205. chatDiv.append(lineBreak)
  206. const inputText = document.createElement('textarea')
  207. inputText.maxlength = 500
  208. inputText.required
  209. inputText.style.cssText = `
  210. resize: none;
  211. margin: 20px 0px;
  212. height: 90px;
  213. width: 90%;
  214. `
  215. inputText.placeholder = 'Введите текст сообщения'
  216. inputText.value = 'Hi everyone!'
  217. chatDiv.append(inputText)
  218. lineBreak = document.createElement('br')
  219. chatDiv.append(lineBreak)
  220. const sendBtn = document.createElement('button')
  221. sendBtn.innerText = 'Send'
  222. sendBtn.style.padding = '3px 40px'
  223. chatDiv.append(sendBtn)
  224. // отправка сообщения по нажатию кнопки
  225. let getMessageId = 0
  226. // async function sendMessage(nick, message) отсылает сообщение.
  227. async function sendMessage() {
  228. const result = jsonPost('http://students.a-level.com.ua:10012', { func: 'addMessage', nick: `${nickName.value}`, message: inputText.value })
  229. await result.then(res => getMessageId = res.nextMessageId)
  230. console.log(getMessageId)
  231. return result.data
  232. }
  233. // async function getMessages() получает сообщения и отрисовывает их в DOM
  234. const chat = document.createElement('div')
  235. chat.style.cssText = `
  236. min-height: 500px;
  237. padding: 10px;
  238. height: 60%;
  239. width: 550px;
  240. overflow-y: scroll;
  241. overflow-x: hidden;
  242. `
  243. allChat.append(chat)
  244. let getNewMessageId = 0
  245. async function getMessages(param) {
  246. const result = await jsonPost('http://students.a-level.com.ua:10012', { func: "getMessages", messageId: param })
  247. for (const message of result.data) {
  248. const chatBlock = document.createElement('div')
  249. chatBlock.style.cssText = `
  250. border: 1px solid #e5e5e5;
  251. border-radius: 10px;
  252. width: 500px;
  253. padding: 10px;
  254. margin-bottom: 20px;
  255. box-shadow: 5px 5px 10px 0px rgb(173 173 173);
  256. `
  257. chat.prepend(chatBlock)
  258. for (const [key, value] of Object.entries(message)) {
  259. const messageBlock = document.createElement('p')
  260. messageBlock.style.margin = '5px 0'
  261. messageBlock.innerHTML = `<span style = 'font-weight: 800;'>${key}</span>: ${typeof value === 'string' ? value : new Date(value)}`
  262. chatBlock.append(messageBlock)
  263. }
  264. }
  265. getNewMessageId = result.nextMessageId
  266. return result.data
  267. }
  268. getMessages(getNewMessageId)
  269. // async function sendAndCheck() использует две предыдущие для минимизации задержки между отправкой сообщения и приходом их.Именно эта функция должна запускаться по кнопке.
  270. async function sendAndCheck() {
  271. await Promise.all([sendMessage(), getMessages(getNewMessageId)])
  272. }
  273. sendBtn.onclick = () => sendAndCheck()
  274. // async function checkLoop() использует delay и бесконечный цикл для периодического запуска getMessages().
  275. async function checkLoop(param) {
  276. const delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms))
  277. while (true) {
  278. await delay(param).then(() => getMessages(getNewMessageId))
  279. }
  280. }
  281. checkLoop(5000)
  282. }
  283. // stage 6
  284. // Заменить внутренности jsonPost на код, использующий fetch вместо XMLHttpRequest.
  285. {
  286. function jsonPost(url, data) {
  287. return new Promise((resolve, reject) => {
  288. fetch(url, { method: 'POST', body: JSON.stringify(data) })
  289. .then(res => res.json())
  290. .then(data => resolve(data), () => reject(new Error('status is not 200')))
  291. })
  292. }
  293. // общий div
  294. const allChat = document.createElement('div')
  295. allChat.style.cssText = `
  296. margin: 0 auto;
  297. width: min-content;
  298. padding: 10px;
  299. border: 1px solid #e5e5e5;
  300. border-radius: 10px;
  301. box-shadow: 5px 5px 10px 0px rgb(173 173 173);
  302. `
  303. document.body.append(allChat)
  304. const chatDiv = document.createElement('div')
  305. chatDiv.style.cssText = `
  306. border: 1px solid #e5e5e5;
  307. width: 550px;
  308. padding: 10px;
  309. margin-bottom: 20px;
  310. `
  311. allChat.append(chatDiv)
  312. const nickName = document.createElement('input')
  313. nickName.type = 'text'
  314. nickName.placeholder = 'Введите свой никнейм'
  315. nickName.value = 'Anon'
  316. chatDiv.append(nickName)
  317. let lineBreak = document.createElement('br')
  318. chatDiv.append(lineBreak)
  319. const inputText = document.createElement('textarea')
  320. inputText.maxlength = 500
  321. inputText.required
  322. inputText.style.cssText = `
  323. resize: none;
  324. margin: 20px 0px;
  325. height: 90px;
  326. width: 90%;
  327. `
  328. inputText.placeholder = 'Введите текст сообщения'
  329. inputText.value = 'Hi everyone!'
  330. chatDiv.append(inputText)
  331. lineBreak = document.createElement('br')
  332. chatDiv.append(lineBreak)
  333. const sendBtn = document.createElement('button')
  334. sendBtn.innerText = 'Send'
  335. sendBtn.style.padding = '3px 40px'
  336. chatDiv.append(sendBtn)
  337. // отправка сообщения по нажатию кнопки
  338. let getMessageId = 0
  339. // async function sendMessage(nick, message) отсылает сообщение.
  340. async function sendMessage() {
  341. const result = jsonPost('http://students.a-level.com.ua:10012', { func: 'addMessage', nick: `${nickName.value}`, message: inputText.value })
  342. await result.then(res => getMessageId = res.nextMessageId)
  343. console.log(getMessageId)
  344. return result.data
  345. }
  346. // async function getMessages() получает сообщения и отрисовывает их в DOM
  347. const chat = document.createElement('div')
  348. chat.style.cssText = `
  349. min-height: 500px;
  350. padding: 10px;
  351. height: 60%;
  352. width: 550px;
  353. overflow-y: scroll;
  354. overflow-x: hidden;
  355. `
  356. allChat.append(chat)
  357. let getNewMessageId = 0
  358. async function getMessages(param) {
  359. const result = await jsonPost('http://students.a-level.com.ua:10012', { func: "getMessages", messageId: param })
  360. for (const message of result.data) {
  361. const chatBlock = document.createElement('div')
  362. chatBlock.style.cssText = `
  363. border: 1px solid #e5e5e5;
  364. border-radius: 10px;
  365. width: 500px;
  366. padding: 10px;
  367. margin-bottom: 20px;
  368. box-shadow: 5px 5px 10px 0px rgb(173 173 173);
  369. `
  370. chat.prepend(chatBlock)
  371. for (const [key, value] of Object.entries(message)) {
  372. const messageBlock = document.createElement('p')
  373. messageBlock.style.margin = '5px 0'
  374. messageBlock.innerHTML = `<span style = 'font-weight: 800;'>${key}</span>: ${typeof value === 'string' ? value : new Date(value)}`
  375. chatBlock.append(messageBlock)
  376. }
  377. }
  378. getNewMessageId = result.nextMessageId
  379. return result.data
  380. }
  381. getMessages(getNewMessageId)
  382. // async function sendAndCheck() использует две предыдущие для минимизации задержки между отправкой сообщения и приходом их.Именно эта функция должна запускаться по кнопке.
  383. async function sendAndCheck() {
  384. await Promise.all([sendMessage(), getMessages(getNewMessageId)])
  385. }
  386. sendBtn.onclick = () => sendAndCheck()
  387. // async function checkLoop() использует delay и бесконечный цикл для периодического запуска getMessages().
  388. async function checkLoop(param) {
  389. const delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms))
  390. while (true) {
  391. await delay(param).then(() => getMessages(getNewMessageId))
  392. }
  393. }
  394. checkLoop(5000)
  395. }
  396. }
  397. // SWAPI Links
  398. // Напишите промисифицированную функцию, которая будет принимать параметром ссылку на swapi.dev(например, https://swapi.dev/api/people/20) и скачивать всю информацию по ссылке, включая вложенные ссылки. Все ссылки внутри скачанного объекта должны заменяться на скачанные объекты. Полученный общий объект должен стать результатом промиса, который возвращает функция.
  399. {
  400. const swapiLinks = async (url) => {
  401. let result = {}
  402. let arrWithLinks = []
  403. let arrWithPromises = []
  404. const hero = await fetch(url)
  405. const heroData = await hero.json()
  406. for (const [key, values] of Object.entries(heroData)) {
  407. // сортируем массивы/ссылки/строки из fetch и складываем ссылки (обычные и из массивов) в новый массив
  408. if (Array.isArray(values)) {
  409. if (values.length > 0) {
  410. for (const value of values) {
  411. arrWithLinks.push({
  412. [key]: value,
  413. })
  414. }
  415. } else {
  416. result[key] = values
  417. }
  418. } else if (values.startsWith('https://swapi.dev/api/')) {
  419. arrWithLinks.push({
  420. [key]: values,
  421. })
  422. } else {
  423. result[key] = values
  424. }
  425. }
  426. // итерируем новый массив со ссылками, запускаем параллельный fetch для каждой ссылки
  427. for (const item of arrWithLinks) {
  428. for (const [keyToParse, urlToParse] of Object.entries(item)) {
  429. arrWithPromises.push(fetch(urlToParse)
  430. .then(res => res.json())
  431. .then(res => {
  432. let itemOfPromise = {
  433. [keyToParse]: res
  434. }
  435. return itemOfPromise
  436. }))
  437. }
  438. }
  439. // парсим все ссылки и возвращаем все в объект
  440. const resultsAll = Promise.all(arrWithPromises)
  441. .then(res => {
  442. // собираем все обратно в лоб
  443. let arrKeys = []
  444. let resultObj = {}
  445. // удаляем дубли повторяющихся ключей и пушим оригинальные в массив
  446. for (const item of res) {
  447. for (const key in item) {
  448. if (!(arrKeys.includes(key))) {
  449. arrKeys.push(key)
  450. }
  451. }
  452. }
  453. // собираем все в один объект с массивами в ключах
  454. for (const item of arrKeys) {
  455. resultObj[item] = []
  456. for (const itemObject of res) {
  457. for (const [key, value] of Object.entries(itemObject)) {
  458. if (key === item) {
  459. resultObj[item].push(value)
  460. }
  461. }
  462. }
  463. }
  464. Object.assign(result, resultObj)
  465. return result // расскомментировать, когда будет все готово. этот result отвечает за вывод всего в консоль
  466. })
  467. return resultsAll;
  468. }
  469. swapiLinks("https://swapi.dev/api/people/20/")
  470. .then(res => console.log('FULL RESULT: ', JSON.stringify(res, null, 4)))
  471. }
  472. // domEventPromise
  473. // Реализуйте промисифицированную функцию, которая резолвит промис по событию в DOM:
  474. // Функция должна:
  475. // используя addEventListener повесить свой обработчик события на DOM element событие eventName
  476. // по событию зарезолвить промис отдав в качестве результата объект события
  477. // убрать обработчик с DOM - элемента, используя removeEventListener.
  478. {
  479. function domEventPromise(element, nameOfEvent) {
  480. function executor(resolve) {
  481. function event(param) {
  482. element.disabled = true;
  483. element.removeEventListener(nameOfEvent, event);
  484. setTimeout(() => resolve(param), 3000);
  485. }
  486. element.disabled = false;
  487. element.addEventListener(nameOfEvent, event)
  488. }
  489. return new Promise(executor);
  490. }
  491. }