HW17.js 21 KB

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