Ivan Asmer %!s(int64=7) %!d(string=hai) anos
pai
achega
1b7df0fda5
Modificáronse 1 ficheiros con 129 adicións e 0 borrados
  1. 129 0
      A/ChatHW.md

+ 129 - 0
A/ChatHW.md

@@ -0,0 +1,129 @@
+# Chat Homework
+
+## Этапы.
+Используя функцию `jsonPost` на адрес http://students.a-level.com.ua:10012 напишите чат-клиент, который:
+### Stage 1
+Отправляет сообщения в чат. Для проверки отслеживайте приходящий с сервера `nextMessageId`, который должен увеличиваться.
+**Интерфейс:** поле ввода ника, поле ввода сообщения, кнопка отправки.
+
+### Stage 2
+
+Читает только *новые* сообщения из чата. Для этого надо после каждого получения запоминать `nextMessageId` и отправлять его 
+при следующем запросе новых сообщений. Изначально `nextMessageId` равен нулю, что бы вычитать всю историю сообщений с сервера.
+**Интерфейс:** некий `div`-контейнер, в котором на каждое сообщение создается `div` (или иной блочный контейнерный тэг) и в 
+него помещается ник и сообщение. Также там есть `timestamp` который может показывать время отправки сообщения.
+
+### Stage 3
+
+Делаем **Stage 2** в `setInterval` для периодической проверки сообщений (раз в 2 -5 секунд).
+
+### Stage 4
+Напишите асинхронную функцию отправки, которая внутри себя будет делать два запроса: на отправку и на проверку, для того что бы 
+минимизировать задержку между отправкой сообщения пользователя и его появлении в окне чата. Оформите отдельно функции отправки и 
+проверки новых сообщений как асинхронные (`async`, возвращает `Promise`)
+
+
+## Информанция
+
+### `jsonPost`
+
+Данная промисифицированная функция (кстати, сделайте из неё асинхронную) умеет общаться с моим чат-сервером отправляя **RPC** 
+запросы используя **JSON**. Это как вызов функций, только удаленно, имя функции и параметры передаются AJAX-ом в формате **JSON**.
+
+```javascript
+function jsonPost(url, data)
+    {
+        return new Promise((resolve, reject) => {
+            var x = new XMLHttpRequest();   
+            x.onerror = () => reject(new Error('jsonPost failed'))
+            //x.setRequestHeader('Content-Type', 'application/json');
+            x.open("POST", url, true);
+            x.send(JSON.stringify(data))
+
+            x.onreadystatechange = () => {
+                if (x.readyState == XMLHttpRequest.DONE && x.status == 200){
+                    resolve(JSON.parse(x.responseText))
+                }
+                else if (x.status != 200){
+                    reject(new Error('status is not 200'))
+                }
+            }
+        })
+    }
+```
+
+Первым параметром указывается **URL** (см. выше) на который отправляется **POST** с **JSON**, вторым - готовый к JSONификации объект, который 
+вы хотите отправить на сервер.
+
+### **RPC**
+
+#### `addMessage`
+Если вы отправите подобный **JSON** на сервер (см `jsonPost`), то сервер запишет ваше сообщение во внутренний массив и отдаст новую длину массива. После этого
+другие могут прочесть это сообщение, используя метод `getMessages`.
+```javascript
+{func: "addMessage", nick: 'msg', message: 'msg'}
+```
+Поле `func` является **обязательным** и содержит имя функции, которая должна быть вызвана на сервере. Функция на сервере получает параметром остальной объект (поля `nick` и `message`)
+**В ответ** вы получите так же объект:
+```javascript
+{nextMessageId: 100500} 
+```
+где 100500: новая длина массива сообщений на сервере после добавления вашего сообщения.
+
+#### `getMessages`
+
+Позволяет прочесть *часть* массива сообщений от отпределенного индекса и до конца. Используется для последовательной *дочитки новых* сообщений. Для этого надо передать в `jsonPost` подобный объект:
+```javascript
+{func: "getMessages", messageId: 0}
+```
+При значении 0 в `messageId` сервер отдаст сообщения от 0 до конца, т. е. весь массив:
+```javascript
+{
+	"data": [
+		{
+			"nick": "test",
+			"message": "test",
+			"timestamp": 1524225450317
+		},
+		{
+			"nick": "test",
+			"message": "test2",
+			"timestamp": 1524225460973
+		},
+		{
+			"nick": "test",
+			"message": "test3",
+			"timestamp": 1524225504849
+		},
+		{
+			"nick": "SirkoSobaka",
+			"message": "Hello!",
+			"timestamp": 1524226323310
+		},
+		{
+			"nick": "SirkoSobaka",
+			"message": "Hello!",
+			"timestamp": 1524226326628
+		},
+	],
+	"nextMessageId": 5
+}
+```
+После чего вы итерируете по `data` и выводите каждый отдельный объект как **DOM**-элемент с текстом, и, возможно, вложенной версткой (время в отдельном элементе и т.п.)
+
+`nextMessageId` вы запоминаете для того, что бы отправить следующий запрос начиная с него (т. е. с 5 в примере выше). Тогда сервер отдаст вам *только сообщения новее последнего
+запроса*.
+
+### Chat Server
+Можно глянуть тут: http://gitlab.a-level.com.ua/gitgod/FrontendLectures/src/master/chatServer/server.js 
+Обратите внимание на массив `messages` и на функции в ассоциативном массиве `RPCFuncs`. А также на 
+http://gitlab.a-level.com.ua/gitgod/FrontendLectures/src/master/chatServer/server.js#L43-L51
+
+### Спойлер
+
+http://chat.asmer.fe.a-level.com.ua/
+
+Но вам все равно надо переписать это на `async`, `await`, `Promise` и **DOM**.
+
+
+## Удачи :-)