Back-End

17 nov, 2014

Brincando com websockets, angularjs e socket.io

902 visualizações
Publicidade

Sou um grande fã de websockets. Tenho vários artigos sobre o assunto (aqui, aqui). Nos últimos meses, eu tenho trabalhado em projetos com angularjs e por conta disso quero brincar um pouco com websockets (com socket.io) e angularjs.

Eu quero construir um serviço em angular.

angular.module('io.service', []).
    factory('io', function ($http) {
        var socket,
            apiServer,
            ioEvent,
            watches = {};
 
        return {
            init: function (conf) {
                apiServer = conf.apiServer;
                ioEvent = conf.ioEvent;
 
                socket = io.connect(conf.ioServer);
                socket.on(ioEvent, function (data) {
                    return watches.hasOwnProperty(data.item) ? watches[data.item](data) : null;
                });
            },
 
            emit: function (arguments) {
                return $http.get(apiServer + '/request', {params: arguments});
            },
 
            watch: function (item, closure) {
                watches[item] = closure;
            },
 
            unWatch: function (item) {
                delete watches[item];
            }
        };
    });

E agora podemos construir o aplicativo

angular.module('myApp', ['io.service']).
 
    run(function (io) {
        io.init({
            ioServer: 'http://localhost:3000',
            apiServer: 'http://localhost:8080/api',
            ioEvent: 'io.response'
        });
    }).
 
    controller('MainController', function ($scope, io) {
        $scope.$watch('question', function (newValue, oldValue) {
            if (newValue != oldValue) {
                io.emit({item: 'question', newValue: newValue, oldValue: oldValue});
            }
        });
 
        io.watch('answer', function (data) {
            $scope.answer = data.value;
            $scope.$apply();
        });
    });

E esse é o HTML

<!doctype html>
<html>
 
<head>
    <title>ws experiment</title>
</head>
 
<body ng-app="myApp">
 
<div ng-controller="MainController">
 
    <input type="text" ng-model="question">
    <hr>
    <h1>Hello {{answer}}!</h1>
</div>
 
<script src="assets/angular/angular.min.js"></script>
<script src="//localhost:3000/socket.io/socket.io.js"></script>
 
<script src="js/io.js"></script>
<script src="js/app.js"></script>
 
</body>
</html>

A ideia desse aplicativo é de observar a variável de um modelo (‘question’, neste exemplo) e toda vez que mudar vamos mandar o valor para o servidor websocket e vamos fazer algo (vamos converter a string para caixa alta em nosso exemplo).

Como você pode ler em um dos meus textos anteriores, não gosto de enviar mensagens do browser para o servidor websocket diretamente (devido a problemas de autenticação que eu comentei aqui). Eu prefiro usar um servidor (Silex, nesse exemplo).

include __DIR__ . '/../../vendor/autoload.php';
 
use Silex\Application;
use Symfony\Component\HttpFoundation\Request;
 
$app = new Application(['debug' => true]);
$app->register(new G\Io\EmitterServiceProvider());
 
$app->get('/request', function (Application $app, Request $request) {
 
    $params = [
        'item'     => $request->get('item'),
        'newValue' => strtoupper($request->get('newValue')),
        'oldValue' => $request->get('oldValue'),
    ];
 
    try {
        $app['io.emit']($params);
        $params['status'] = true;
    } catch (\Exception $e) {
        $params['status'] = false;
    }
 
    return $app->json($params);
});
 
$app->run();

Você pode acessar o código na minha conta no GitHub.

***

Artigo traduzido pela Redação iMasters com autorização do autor. Publicado originalmente em http://gonzalo123.com/2014/08/25/playing-with-websockets-angularjs-and-socket-io/