02.md 7.8 KB

Часть вторая

Разработка FullStack

Любая разработка итеративна, FullStack при этом итеративен в контексте клиента и сервера - создается какой-то этап на той или иной стороне, после чего пишется ответная часть на противоположной стороне. Такой себе пинг-понг.

Чат

Давайте разберемся с тем, как должен работать чат.

Интерфейс пользователя

Если вы справились с ДЗ, то вы уже имеете шаблон вашей страницы, в котором будет окно для сообщений чата, поле ввода для одного нового сообщения и кнопка отправки. Осталось это оживить - научить нашу страницу общаться с сервером, отправлять и принимать сообщения.

Отправка сообщений

Для общения с сервером мы будем использовать промисифицированную функцию jsonPost. Не вдаваясь в подробности, она обеспечивает прием и передачу данных через интернет, используя AJAX (т. е. работает при этом незаметно для пользователя)

    function jsonPost(url, data)
    {
        return new Promise((resolve, reject) => {
            var x = new XMLHttpRequest();   
            x.onerror = () => reject(new Error('jsonPost failed'))
            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'))
                }
            }
        })
    }

Если вы скопируете этот код в консоль браузера, то сможете запустить эту функцию и отправить данные куда-нибудь.

Первый параметр функции - адрес для отправки. Второй - тот или иной ассоциативный массив, который мы хотим послать на сервер.

Для того, что бы проверить отправку, сделаем простенький бэк-энд на nodejs:

  • создаем папку проекта
  • создаем файл index.js
http = require('http');

server = http.createServer(function(req, res){
    if (req.method == "POST"){
        var body = '';
        req.on('data', function (data) { //сбор информации, она может идти кусками
                body += data;
        });
        req.on('end', function () { //приехали все данные
                console.log("Body: " + body); //выводим
        });

//колдунство, которое позволяет обращаться к нашему серверу откуда угодно (с любого другого домена)
        res.setHeader('Access-Control-Allow-Origin', '*');
        res.setHeader('Access-Control-Request-Method', '*');
        res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST');
        res.setHeader('Access-Control-Allow-Headers', '*');
        res.writeHead(200, {'Content-Type': 'text/json'});
    }
});

//localhost:3000
port = 3000;
host = '127.0.0.1';
server.listen(port, host);
console.log("Listen...");

Запускаем этот файл в папке где он лежит (cmd.exe):

node index.js
jsonPost('http://localhost:3000', {data: "someData", time: (new Date()).getTime()}) //отправляем данные на адрес localhost:3000 с объектом с двумя ключами - data и time

client

и увидеть в консоли, что сервер данные получил:

server

Теперь наша задача - разобраться с тем, откуда взять данные для отправки и отправлять их. Кстати, было бы неплохо в чате добавить еще и имя пользователя. Добавьте его в верстку (еще одно поле input с id="nick")

Отправляем настоящие данные

Давайте договоримся, что данные которые мы отправляем, будут иметь следующую структуру:

{
    action: "ADD_MESSAGE", //при общении с сервером у нас будет несколько операций, какие?
    nick: "Имя пользователя", 
    message: "Сообщение"
}

Добавьте в ваше ДЗ код, который, используя jsonPost будет отправлять реальный nick и message из полей ввода на сервер. Проверьте, что сервер в консоли пишет пришедшие данные.

Получение и хранение сообщений на сервере.

Давайте подумаем, какие у нас есть типы данных и какой более всего подходит для хранения сообщений на сервере.

...
    var data = JSON.parse(body);
    if (data.action == 'ADD_MESSAGE'){
        //сохраняем новое сообщение
        console.log()//убеждаемся, что все сохранилось
        res.end(JSON.stringify({status: 'ok'}));
    }
    else {
        console.log('UNKNOWN ACTION')
        console.log(data)
    }
...

Выдача сообщений из сервера на клиент

Для того, что бы клиент "спросил" набор сообщений, пусть будет структура данных следующего вида:

{
    action: 'GET_MESSAGES', //операция получения
}

Сервер: выдача сообщений

...
    if (data.action == 'GET_MESSAGES'){
        res.end(JSON.stringify({status: 'ok', data: ....})) //выдача сообщений в клиент
    }
...

Клиент: обработка пришедших сообщений

В силу наличия асинхронного ада в JS, данные приезжают не сразу, а передаются в функцию впоследствии. Один из подходов - использовать промисы:

jsonPost('http://localhost:3000', { action: 'GET_MESSAGES'}).then( data => console.log(data) ) //данные будут в стрелочной функции в переменной data

Отображения истории сообщений

Теперь надо циклически обработать сообщения и добавить их в окно наших сообщений в чате.

Poll

Используем setInterval для периодической проверки сообщений.

Как проверять?

Откройте две вкладки с чатом и пообщайтесь сами с собой. Приятно же поговорить с умным человеком