Ni HTML ni HTTP fueron creados para aplicaciones web dinámicas. Básicamente, confiamos en los hacks, además de los hacks para dar a nuestras aplicaciones una interfaz de usuario receptiva. AngularJS elimina algunas limitaciones del HTML, lo que nos permite crear y administrar el código de la interfaz de usuario con mayor facilidad. Socket.IO, por otro lado, nos ayuda a enviar datos desde el servidor no solo cuando el cliente lo solicita, sino también cuando el servidor lo necesita. En este artículo, le mostraré cómo combinar estos dos, para mejorar la capacidad de respuesta de sus aplicaciones de una sola página..
En la primera parte de este tutorial crearemos un servicio AngularJS reutilizable para Socket.IO. Por eso reutilizable parte, esto será un poco más complicado que solo usar módulo.servicio ()
o módulo.factory ()
. Estas dos funciones son solo azúcar sintáctica sobre el nivel más bajo módulo.proveedor ()
Método, que utilizaremos para proporcionar algunas opciones de configuración. Si nunca ha usado AngularJS antes, le recomiendo que siga al menos el tutorial oficial y algunos de los tutoriales aquí en Tuts+.
Antes de comenzar a escribir nuestro módulo AngularJS, necesitamos un back-end simple para las pruebas. Si ya está familiarizado con Socket.IO, puede desplazarse hasta el final de esta sección, copiar la fuente de back-end y pasar a la siguiente, si no, siga leyendo..
Solo necesitaremos socket.io
. Puede instalarlo directamente usando el npm
comando así:
npm instalar socket.io
O crear un paquete.json
archivo, ponga esta línea en el dependencias
sección:
"socket.io": "0.9.x"
Y ejecutar el npm instalar
mando.
Como no necesitamos ningún marco web complicado como Express, podemos crear el servidor utilizando Socket.IO:
var io = require ('socket.io') (8080);
Eso es todo lo que necesita para configurar el servidor Socket.IO. Si inicia su aplicación, debería ver un resultado similar en la consola:
Y deberías poder acceder a la socket.io.js
archivo en su navegador en http: // localhost: 8080 / socket.io / socket.io.js:
Manejaremos todas las conexiones entrantes en el conexión
oyente de eventos del io.sockets
objeto:
io.sockets.on ('conexión', función (socket) );
los enchufe
atributo pasado a la devolución de llamada es el cliente que se conectó y podemos escuchar los eventos en él.
Ahora agregaremos un detector de eventos básico en la devolución de llamada anterior. Enviará los datos recibidos, de vuelta al cliente utilizando el socket.emit ()
método:
socket.on ('echo', función (datos) socket.emit ('echo', datos););
eco
es el nombre del evento personalizado que usaremos más adelante.
También utilizaremos agradecimientos en nuestra biblioteca. Esta característica le permite pasar una función como el tercer parámetro de la socket.emit ()
método. Se puede llamar a esta función en el servidor para enviar algunos datos al cliente:
socket.on ('echo-ack', función (datos, devolución de llamada) devolución de llamada (datos););
Esto le permite responder al cliente sin requerir que escuche ningún evento (lo cual es útil si solo desea solicitar algunos datos del servidor).
Ahora nuestro back-end de prueba está completo. El código debería tener este aspecto (Este es el código que debe copiar si omite esta sección.):
var io = require ('socket.io') (8080); io.sockets.on ('connection', function (socket) socket.on ('echo', function (data) socket.emit ('echo', data);); socket.on ('echo-ack ', función (datos, devolución de llamada) devolución de llamada (datos);););
Ahora debe ejecutar la aplicación y dejarla en ejecución antes de continuar con el resto del tutorial..
Por supuesto necesitaremos algo de HTML para probar nuestra biblioteca. Tenemos que incluir AngularJS, socket.io.js
de nuestro back-end, nuestro angular-socket.js
Biblioteca y un controlador AngularJS básico para ejecutar algunas pruebas. El controlador estará en línea en el del documento para simplificar el flujo de trabajo:
Esto es todo lo que necesitamos por ahora, volveremos a la etiqueta de secuencia de comandos vacía más adelante ya que aún no tenemos la biblioteca.
En esta sección crearemos el angular-socket.js
biblioteca. Todo el código debe ser insertado en este archivo.
Vamos a empezar con la creación del módulo para nuestra lib:
var module = angular.module ('socket.io', []);
No tenemos ninguna dependencia, por lo que la matriz en el segundo argumento de angular.module ()
está vacío, pero no lo quite completamente o obtendrá un $ inyector: nomod
error. Esto sucede porque la forma de un argumento de angular.module ()
recupera una referencia al módulo ya existente, en lugar de crear uno nuevo.
Los proveedores son una de las formas de crear servicios de AngularJS. La sintaxis es simple: el primer argumento es el nombre del servicio (¡no el nombre del proveedor!) Y el segundo es la función constructora para el proveedor:
module.provider ('$ socket', $ socketProvider () );
Para hacer que la biblioteca sea reutilizable, tendremos que permitir cambios en la configuración de Socket.IO. Primero definamos dos variables que contendrán la URL para la conexión y el objeto de configuración (el código en este paso va a la $ socketProvider ()
función):
var ioUrl = "; var ioConfig = ;
Ahora ya que estas variables no están disponibles fuera de la $ socketProvider ()
función (son una especie de privado), tenemos que crear métodos (setters) para cambiarlos. Podríamos, por supuesto, simplemente hacerlos público Me gusta esto:
this.ioUrl = "; this.ioConfig = ;
Pero:
Function.bind ()
Más tarde para acceder al contexto apropiado para esta
falso
como el 'tiempo de espera de conexión'
opciónUna lista completa de opciones para el Cliente de Socket.IO se puede ver en su wiki de GitHub. Crearemos un setter para cada uno de ellos más uno para la URL. Todos los métodos son similares, por lo que explicaré el código de uno de ellos y colocaré el resto a continuación..
Vamos a definir el primer método:
this.setConnectionUrl = función setConnectionUrl (url)
Debe comprobar el tipo de parámetro pasado en:
if (typeof url == 'string')
Si es el que esperábamos, configura la opción:
ioUrl = url;
Si no, debe tirar. Error de tecleado
:
else throw new TypeError ('url debe ser de tipo string'); ;
Para el resto de ellos, podemos crear una función de ayuda para mantenerlo SECO:
función setOption (nombre, valor, tipo) si (tipo de valor! = tipo) lanzar un nuevo tipo de error de tipo ("'" + nombre + "' debe ser de tipo '" + tipo + "'"); ioConfig [nombre] = valor;
Solo tira Error de tecleado
si el tipo es incorrecto, de lo contrario establece el valor. Aquí está el código para el resto de las opciones:
this.setResource = función setResource (valor) setOption ('recurso', valor, 'cadena'); ; this.setConnectTimeout = función setConnectTimeout (valor) setOption ('tiempo de espera de conexión', valor, 'número'); ; this.setTryMultipleTransports = función setTryMultipleTransports (value) setOption ('try multiple transports', value, 'boolean'); ; this.setReconnect = función setReconnect (value) setOption ('reconnect', value, 'boolean'); ; this.setReconnectionDelay = function setReconnectionDelay (value) setOption ('retardo de reconexión', valor, 'número'); ; this.setReconnectionLimit = función setReconnectionLimit (valor) setOption ('límite de reconexión', valor, 'número'); ; this.setMaxReconnectionAttempts = función setMaxReconnectionAttempts (valor) setOption ('intentos máximos de reconexión', valor, 'número'); ; this.setSyncDisconnectOnUnload = función setSyncDisconnectOnUnload (value) setOption ('sync disconnect on unload', value, 'boolean'); ; this.setAutoConnect = función setAutoConnect (value) setOption ('auto connect', value, 'boolean'); ; this.setFlashPolicyPort = función setFlashPolicyPort (valor) setOption ('puerto de política de flash', valor, 'número'); this.setForceNewConnection = función setForceNewConnection (value) setOption ('force new connection', value, 'boolean'); ;
Podrías reemplazarlo con una sola. setOption ()
Método, pero parece más fácil escribir el nombre de la opción en el caso del camello, en lugar de pasarlo como una cadena con espacios.
Esta función creará el objeto de servicio que podemos usar más adelante (por ejemplo, en los controladores). Primero, llamemos al io ()
Función para conectarse al servidor Socket.IO:
este. $ get = function $ socketFactory ($ rootScope) var socket = io (ioUrl, ioConfig);
Tenga en cuenta que estamos asignando la función a la $ obtener
propiedad del objeto creado por el proveedor - esto es importante ya que AngularJS usa esa propiedad para llamarlo. Tambien ponemos $ rootScope
como su parametro. En este punto, podemos utilizar la inyección de dependencia de AngularJS para acceder a otros servicios. Lo utilizaremos para propagar cambios a cualquier modelo en las devoluciones de llamada de Socket.IO.
Ahora la función necesita devolver un objeto:
regreso ; ;
Pondremos todos los métodos para el servicio en ella..
en()
MétodoEste método adjuntará un detector de eventos al objeto socket, por lo que podemos utilizar cualquier información enviada desde el servidor:
on: function on (event, callback)
Utilizaremos Socket.IO's. socket.on ()
para adjuntar nuestra devolución de llamada y llamarlo en AngularJS's $ scope. $ apply ()
método. Esto es muy importante, porque los modelos solo pueden modificarse dentro de él:
socket.on (evento, función ()
Primero, tenemos que copiar los argumentos a una variable temporal para poder usarlos más adelante. Los argumentos son, por supuesto, todo lo que el servidor nos envió:
var args = argumentos;
A continuación, podemos llamar a nuestro callback usando Function.apply ()
para pasarle argumentos:
$ rootScope. $ apply (function () callback.apply (socket, args);); ); ,
Cuando enchufe
El emisor de eventos llama a la función de escucha que utiliza. $ rootScope. $ apply ()
para llamar a la devolución de llamada proporcionada como el segundo argumento a la .en()
método. De esta manera, puede escribir sus detectores de eventos como lo haría para cualquier otra aplicación que use Socket.IO, pero puede modificar los modelos de AngularJS en ellos..
apagado()
MétodoEste método eliminará uno o todos los escuchas de eventos para un evento determinado. Esto le ayuda a evitar pérdidas de memoria y comportamientos inesperados. Imagina que estás usando ngRuta
y se adjuntan pocos oyentes en cada controlador. Si el usuario navega a otra vista, su controlador se destruye, pero el detector de eventos permanece conectado. Después de algunas navegaciones y tendremos una pérdida de memoria..
off: función off (evento, devolución de llamada)
Solo tenemos que comprobar si el llamar de vuelta
fue proporcionado y llamar socket.removeListener ()
o socket.removeAllListeners ()
:
if (typeof callback == 'function') socket.removeListener (event, callback); else socket.removeAllListeners (event); ,
emitir()
MétodoEste es el último método que necesitamos. Como su nombre lo sugiere, este método enviará datos al servidor:
emitir: función emit (evento, datos, devolución de llamada)
Dado que Socket.IO admite reconocimientos, verificaremos si el llamar de vuelta
fue dado. Si lo fuera, usaremos el mismo patrón que en el en()
método para llamar a la devolución de llamada dentro de $ scope. $ apply ()
:
if (typeof callback == 'function') socket.emit (event, data, function () var args = argumentos; $ rootScope. $ apply (function () callback.apply (socket, args);); );
Si no hay llamar de vuelta
solo podemos llamar socket.emit ()
:
else socket.emit (evento, datos);
Para probar la biblioteca, crearemos un formulario simple que enviará algunos datos al servidor y mostrará la respuesta. Todo el código JavaScript en esta sección debe ir en el >