Введение
Для Node.js есть отличная библиотека Socket.io для кроссбраузерного использования вебсокетов.
Но для двухстороннего взаимодействия сервера и клиента приходится использовать модель сообщений.
С помощью библиотеки Now.js есть возможность прозрачного вызова функций клиента со стороны сервера и наоборот.
Как это выглядит
Now.js — Node.js модуль поверх Socket.io, предоставляющий возможности вызова функций клиента со стороны сервера и наоборот. Также со стороны клиента и сервера можно не только вызывать функции, но и использовать общие переменные.
Для начала обсудим минимум кода, который нужен для того, чтобы у нас заработали удаленные вызовы.
Серверная часть
rpc = require "now"
rpc_channel = rpc.initialize httpServer
rpc_channel.now.myVariable = "some value"
rpc_channel.now.distribute = (message) ->
rpc_channel.now.receive @now.name, message
Этот исходный код отформатирован с помощью FractalizeR's HabraSyntax Source Code Highlighter.
Что здесь происходит:
- Загружаем модуль Now.js
- Создаем канал для вызова методов, передавая методу initialize экземпляр запущенного Node.js сервера(http.Server)
- В полученном канале есть объект now через который и идет синхронизация между клиентом и сервером. Для примера в объект помещена переменная myVariable, которая будет видна клиентам
- Помещаем в объект now функцию distribute, теперь ее могут вызывать клиенты
- В функции distribute вызываем метод receive у клиента
Клиентская часть
console.log(now.myVariable);
now.receive = function(message){
$("#messages").append("<br>"+message);
}
$("#send-button").click(function(){
now.distribute($("#text-input").val());
});
Этот исходный код отформатирован с помощью FractalizeR's HabraSyntax Source Code Highlighter.
Что здесь происходит:
- Некоторым образом используем переменную определенную на сервере
- Определяем функцию, которую сможет вызвать сервер(объект now похож на серверный)
- В некотором месте(в данном случае в обработчике события нажатия на кнопку) мы вызываем серверную функцию
Пишем чат с использованием Now.js и Kiss.js
Контроллер
kiss = require "kiss.js"
rpc = kiss.controllers.rpc
class MyController
@on_app_started = (app) ->
app.rpc_channel.now.distributeMessage = (message) ->
gr = rpc.getGroup @now.room
gr.removeUser @user.clientId
gr = rpc.getGroup @now.new_room
gr.addUser @user.clientId
@now.room = @now.new_room
gr.now.receiveMessage @now.name, message
@index = (req, res) ->
context = { template_name: "chat.html" }
v = new kiss.views.TextViewer()
v.render req, res, context
exports.MyController = MyController
Этот исходный код отформатирован с помощью FractalizeR's HabraSyntax Source Code Highlighter.
В index мы просто генерируем страницу чата, а вот все самое интересное происходит в on_app_started.
Этот метод выполняется при старте приложения. Здесь мы определяем функцию distributeMessage, которую будет вызывать клиент. При вызове мы перемещаем пользователя в комнату new_room и рассылаем всем сообщение.
Клиент
$(document).ready(function()
{
now.name = "user";
now.room = "room 1";
function send()
{
now.name = $('<div/>').text($("#username").val()).html();
now.new_room = $('<div/>').text($("#room").val()).html();
var html = $('<div/>').text($("#text-input").val()).html();
now.distributeMessage(html);
$("#text-input").val("");
}
$("#send-button").click(send);
$("#text-input").keypress(function(e)
{
if(e.keyCode == 13) send();
});
now.receiveMessage = function(name, message)
{
$("<li><h3>" + name + "</h3><p><strong>" + message + "</strong></p></li>").prependTo("#messages");
$('#messages').listview('refresh');
}
});
Этот исходный код отформатирован с помощью FractalizeR's HabraSyntax Source Code Highlighter.
При загрузке документа указываем имя пользователя и комнату по умолчанию и создаем функцию, которая будет вызвана при щелчке по кнопке. В этой функции мы получаем имя, комнату и сообщение и отсылаем все это на сервер.
Также мы определяем функцию, которую вызовет сервер для уведомления о получении сообщения.
Результат можно посмотреть здесь.
Люди в комнате с одним названием будут видеть сообщения друг друга, сообщения нигде не сохраняются, так как это просто тестовый пример.
Как видим с помощью Now.js мы имеем возможность синхронизации переменных и прозрачного вызова функций и со стороны сервера, и со стороны клиента, что может быть удобно при построении приложений реального времени.
Ссылки
Демо
Исходный код чата
Now.js
Socket.io
Kiss.js