Patrón Singleton en nodejs – es necesario?

Recientemente me encontré con este artículo sobre cómo escribir un singleton en Node.js. Sé que la documentación de require los estados que:

Módulos se almacenan en caché después de la primera vez que se cargan. Varias llamadas a require('foo') no puede hacer que el módulo de código para que se ejecute varias veces.

Así que parece que cada módulo requerido puede ser fácilmente utilizado como un singleton sin el singleton repetitivo-código.

Pregunta:

Hace el artículo anterior proporcionar una serie acerca de la solución para la creación de un singleton?

InformationsquelleAutor mkoryak | 2012-11-01

9 Kommentare

  1. 41

    Esto tiene básicamente que ver con nodejs el almacenamiento en caché. Simple y sencillo.

    https://nodejs.org/api/modules.html#modules_caching

    (v 6.3.1)

    De almacenamiento en caché

    Módulos se almacenan en caché después de la primera vez que se cargan. Esto significa
    (entre otras cosas) de que cada llamada a exigir(‘foo’) se obtiene
    exactamente el mismo objeto devuelto, si se resuelve a la misma
    archivo.

    Varias llamadas a exigir(‘foo’) no puede causar el módulo de código
    ejecuta varias veces. Esta es una característica importante. Con ella,
    «parcialmente hecho» los objetos pueden ser devueltos, permitiendo así transitiva
    dependencias de carga incluso cuando podría causar ciclos.

    Si quieres tener un módulo de ejecución de código varias veces, luego de exportación
    una función, y llame a esa función.

    Módulo De Almacenamiento En Caché De Advertencias

    Módulos se almacenan en caché basado en sus resuelto nombre de archivo. Debido a que los módulos de mayo
    resolver un nombre de archivo diferente, basado en la ubicación de la llamada
    (módulo de carga de node_modules carpetas), no es una garantía de que
    require(‘foo’) siempre devuelve el mismo objeto, si es que
    resolver a diferentes archivos.

    Además, en caso de insensibilidad a los sistemas de archivos o sistemas operativos,
    diferentes resuelve los nombres de archivo pueden señalar el mismo archivo, pero la caché
    todavía tratan como diferentes módulos y volver a cargar el archivo
    en múltiples ocasiones. Por ejemplo, require(‘./foo’) y require(‘./FOO’)
    retorno de dos objetos diferentes, independientemente de si o no ./foo y
    ./FOO son el mismo archivo.

    Así que en términos sencillos.

    Si quieres un Singleton; exportar un objeto.

    Si usted no desea un Singleton; exportar una función (y hacer cosas/retorno cosas/lo que sea en esa función).

    A ser MUY claro, si haces esto correctamente se debe trabajar, mirar https://stackoverflow.com/a/33746703/1137669 (Allen Luce la respuesta). Se explica en el código de lo que sucede cuando la caché de falla debido a la diferente resuelve los nombres de archivo. Pero si SIEMPRE se resuelven con el mismo nombre se debe trabajar.

    • Si quieres un Singleton; exportar un objeto … que ayudaron gracias
    • Esta es una mala idea – por muchas razones dadas en esta página, pero el concepto es esencialmente válido, es decir, que en virtud de lo establecido nominal de las circunstancias, de los reclamos en esta respuesta son verdaderas. Si desea una rápida y sucia singleton, esto probablemente va a trabajar, simplemente no se puede iniciar cualquier lanzaderas con el código.
    • muchas razones dadas en esta página», ¿se refiere a crear enlace simbólico para los archivos o falta de ortografía, nombres de archivo que al parecer no utilizan la misma memoria caché? Que hace el estado en la documentación de la cuestión en relación con el caso de insensibilidad a los sistemas de archivos o sistemas operativos. Con respecto a crear enlace simbólico para, usted puede leer más aquí, como se discutió github.com/nodejs/node/issues/3402. Además, si usted es crear enlace simbólico para los archivos o no entiende su sistema operativo y el nodo correctamente, entonces no debería estar en cualquier lugar cerca de la ingeniería aeroespacial, la industria ;), sin embargo, entiendo perfectamente tu punto^^.
    • sólo por el hecho de que la documentación no garantiza, el hecho de que parece ser que no especificados de comportamiento, o cualquier otro motivo racional para no confiar en este particular comportamiento de la lengua. Tal vez la memoria caché funciona de manera diferente en otra aplicación, o te gusta el trabajo en REPL y subvertir la función de almacenamiento en caché por completo. Mi punto es que el caché es un detalle de implementación, y usarlo como un singleton equivalente es un hack inteligente. Me encanta inteligente hacks, pero deben ser diferenciados, para todo ( también nadie es el lanzamiento de transbordadores con el nodo, yo estaba haciendo el tonto )
  2. 135

    Todo lo anterior, es demasiado complicado. Hay una escuela de pensamiento que dice que los patrones de diseño están mostrando deficiencias de lenguaje real.

    Idiomas con un prototipo basado en la programación orientada a objetos (sin clases) no necesitan de un patrón singleton en todo. Solo tiene que crear una sola(ton) objeto sobre la marcha y, a continuación, utilizarlo.

    Como para los módulos en node, sí, por defecto se almacenan en caché, pero puede ser ajustado por ejemplo, si desea caliente de carga de módulo de cambios.

    Pero sí, si desea utilizar el objeto compartido todo, ponerlo en un módulo de exportaciones está bien. No se complique con el «patrón singleton», sin necesidad de JavaScript.

    • Es raro, nadie está siendo upvotes… tienen un +1 para There is a school of thought which says design patterns are showing deficiencies of actual language.
    • Los únicos no son un anti-patrón.
    • href=»http://programmers.stackexchange.com/questions/40373/so-singletons-are-bad-then-what» title=»así que los únicos son malos entonces, ¿qué»>programmers.stackexchange.com/questions/40373/…, leer el aceptado respuesta.
    • parece demasiado específica (y, por tanto, incorrecto) la definición del patrón singleton.
    • AFAIK, que es el patrón singleton (IOW, la definición es correcta). Singleton es realmente único-global-punto accesible solo objeto, la mayoría del tiempo perezoso inicializado (de la wikipedia: «la Implementación de un patrón singleton debe satisfacer la instancia única y global de los principios de acceso»).
    • Si estoy leyendo esta respuesta correctamente, la única solución para el problema que se presenta es a depender de la carga-una vez que la función de los módulos. No entiendo cómo un objeto singleton creado «sobre la marcha» en un módulo de otro modo se convierte en accesible a otro módulo. O estás diciendo que la pregunta no debería haber sido formulada utilizando la palabra «singleton»? Si el último, ¿a qué plazo se adapta mejor a un único recurso al que se puede acceder a múltiples módulos de node.js? Me temo que yo le hubiera preguntado a la pregunta de la misma manera.
    • La documentación se lee: «Varias llamadas a exigir(‘foo’) no causa el módulo de código para que se ejecute varias veces.». Dice «no», no dice «no», así que preguntando cómo asegurarse de que el módulo se crea la instancia de una sola vez en una aplicación es una pregunta válida desde mi punto de vista.
    • Es, sin embargo, si es que ‘foo’ siempre se traduce en el mismo módulo utilizando la misma vía. Que, a menos que usted haga un poco de magia negra, siempre lo hace.
    • Es falso que esta es la respuesta correcta para esta pregunta. Como @mike se señala más adelante, es posible que un módulo se carga más de una vez y usted tiene dos instancias. Estoy golpeando ese problema, donde sólo tengo una copia de knock-out, pero dos instancias se crean debido a que el módulo está cargado dos veces.
    • nodo almacena en caché los módulos por ruta completa del archivo. Así que si usted carga el mismo módulo dos veces, usted consigue solamente una instancia. Tal vez el problema con el que la instalación es que knockout mecanismo nacional de prevención de la dependencia de dos módulos diferentes, por lo tanto presente en dos lugares diferentes. Hay una solución para eso, sin embargo. IIRC: npm 2.0 ya vuelve a utilizar la parte superior de las dependencias de nivel, por lo que debe incluir la cobertura como la dependencia directa en el paquete.json y reinstalar mecanismo nacional de prevención deps (rm node_modules && npm install).
    • El dominio de aplicación de javascript es cada vez mayor. Con el nodo js tenemos que fluye de escritorio/servidor de aplicación que viene en la imagen. Yo no encuentro nada malo en el uso de términos que son estándar en la industria para la solución/definición del problema.
    • Este no-respuesta ignora/los errores de lo que es un singleton. Un singleton es un solo y mismo objeto (referencia) a través de múltiples contextos, los cuales no pueden ser creados sobre la marcha, por definición. Los únicos son útiles en una variedad de casos, y puede ser implementado a través de diversos medios en js, cualquiera de los cuales sólo necesitan asegurarse de que todas las referencias a un objeto son el mismo. Confiando en el nodo del hábito de almacenamiento en caché de objetos antiguos es un ejemplo de ello, si no es una gran idea, el concepto es todavía válida. Otras soluciones que se ofrecen aquí son probablemente una mejor idea.

  3. 23

    No. Cuando el Nodo del módulo de almacenamiento en caché de falla, que el patrón singleton falla. He modificado el ejemplo para que se ejecute de manera significativa en OSX:

    var sg = require("./singleton.js");
    var sg2 = require("./singleton.js");
    sg.add(1, "test");
    sg2.add(2, "test2");
    
    console.log(sg.getSocketList(), sg2.getSocketList());

    Esto le da a la salida de la autora previsto:

    { '1': 'test', '2': 'test2' } { '1': 'test', '2': 'test2' }

    Pero con una pequeña modificación de la derrota de almacenamiento en caché. En OSX, hacer esto:

    var sg = require("./singleton.js");
    var sg2 = require("./SINGLETON.js");
    sg.add(1, "test");
    sg2.add(2, "test2");
    
    console.log(sg.getSocketList(), sg2.getSocketList());

    O, en Linux:

    % ln singleton.js singleton2.js

    A continuación, cambiar el sg2 requieren de la línea a:

    var sg2 = require("./singleton2.js");

    Y bam, el singleton es derrotado:

    { '1': 'test' } { '2': 'test2' }

    No sé de una manera aceptable para conseguir alrededor de esto. Si usted realmente siente la necesidad de hacer algo singleton y están de acuerdo con la contaminación del espacio de nombres global (y los muchos problemas que pueden resultar), puede cambiar el autor del getInstance() y exports líneas:

    singleton.getInstance = function(){
      if(global.singleton_instance === undefined)
        global.singleton_instance = new singleton();
      return global.singleton_instance;
    }
    
    module.exports = singleton.getInstance();

    Que dijo, nunca me he encontrado en una situación en un sistema de producción en el que tuve que hacer nada de esto. También he sentido nunca la necesidad de utilizar el patrón singleton en Javascript.

  4. 20

    Mirar un poco más allá en el Módulo De Almacenamiento En Caché De Advertencias en los Módulos docs:

    Módulos se almacenan en caché basado en sus resuelto nombre de archivo. Debido a que los módulos se puede resolver un nombre de archivo diferente, basado en la ubicación de la llamada (módulo de carga de node_modules carpetas), no es una garantía que requieren(‘foo’) siempre devuelve el mismo objeto, si se resuelve a diferentes archivos.

    Así, dependiendo de donde usted cuando usted está requiriendo de un módulo, es posible obtener una instancia diferente de la del módulo.

    Sonidos al igual que los módulos son no una solución sencilla para la creación de los embarazos únicos.

    Edición: O tal vez son. Como @mkoryak, yo no puedo venir con una caja en la que un solo archivo puede resolver nombres de archivo diferentes (sin el uso de enlaces simbólicos). Pero (como @JohnnyHK comentarios), múltiples copias de un mismo archivo en diferentes node_modules directorios de cada ser cargados y almacenados por separado.

    • ok, he leído que 3 veces y todavía no puedo pensar en un ejemplo donde se iba a resolver un nombre de archivo diferente. ayuda?
    • Creo que es el que se refiere a los casos en que tienes dos módulos diferentes que usted está requiriendo de node_modules donde cada dependen del mismo módulo, pero hay copias independientes de que el módulo de dependiente en virtud de la node_modules subdirectorio de cada uno de los dos módulos diferentes.
    • usted está aquí que el módulo de obtener instancias varias veces cuando se hace referencia a través de diferentes caminos. Me golpeó el caso de que al escribir las pruebas unitarias de los módulos de servidor. Necesito tipo de instancia singleton. cómo lograrlo?
    • Un ejemplo podría ser el de las rutas de acceso relativas. por ejemplo. Dado require('./db') es en dos archivos separados, el código para el db módulo se ejecuta dos veces
    • Yo sólo tenía un desagradable error desde el nodo en el sistema de módulos es el caso-insenstivie. me llama require('../lib/myModule.js'); en un archivo y require('../lib/mymodule.js'); en otro y no entregar el mismo objeto.
    • Mi pregunta es sobre la declaración de .... Since modules may resolve to a different filename based on the location of the calling module.. Para mí significa esta declaración nodejs utiliza la ruta de acceso relativa(en lugar de la ruta de acceso absoluta) como clave de caché como dependiente o la ubicación de llamar módulo . Es ese derecho ?

  5. 18

    Un singleton en node.js (o en el explorador de JS, para que la materia) como que es completamente innecesario.

    Debido a que los módulos se almacenan en caché y el estado, el ejemplo dado en el enlace que se ofrece podría fácilmente ser reescrito de forma mucho más simple:

    var socketList = {};
    
    exports.add = function (userId, socket) {
        if (!socketList[userId]) {
            socketList[userId] = socket;
        }
    };
    
    exports.remove = function (userId) {
        delete socketList[userId];
    };
    
    exports.getSocketList = function () {
        return socketList;
    };
    //or
    //exports.socketList = socketList
    • Docs decir «no causa el módulo de código para que se ejecute varias veces», por lo que es posible que se llama varias veces, y si este código se ejecuta de nuevo, la socketList se restablecerán a una lista vacía
    • El contexto de la en la documentación alrededor de esa cita parecen hacer bastante convincente que no está siendo utilizado en un RFC de estilo NO DEBE.
    • es una palabra como esa. Apetece una palabra que cuando negado significa «tal vez no» o «definitivamente no»..
    • El may not se aplica cuando npm link otros módulos durante el desarrollo. Así que tenga cuidado al utilizar los módulos que dependen de una sola instancia como un eventBus.
  6. 9

    No se necesita nada especial para hacer un singleton en js, el código en el artículo bien podría ser:

    var socketList = {};
    
    module.exports = {
          add: function() {
    
          },
    
          ...
    };

    Fuera node.js (por ejemplo, en el explorador js), es necesario agregar la función de contenedor de forma manual (se realiza de forma automática en node.js):

    var singleton = function() {
        var socketList = {};
        return {
            add: function() {},
            ...
        };
    }();
    • Como se ha señalado por @Allen Luce, si el nodo de caché del falla el patrón singleton también falla.
  7. 7

    La única respuesta que utiliza ES6 clases

    //SummaryModule.js
    class Summary {
    
      init(summary) {
        this.summary = summary
      }
    
      anotherMethod() {
        //do something
      }
    }
    
    module.exports = new Summary()

    requieren este singleton con:

    const summary = require('./SummaryModule')
    summary.init(true)
    summary.anotherMethod()

    Único problema aquí es que no se puede pasar parámetros al constructor de la clase, pero que se pueden corregir manualmente llamar a un init método.

    • la pregunta es «son los únicos necesarios», no «¿cómo se escribe una»
    • Cómo podemos usar la misma instancia summary en otra clase, sin inicializar de nuevo?
    • En Node.js solo se requiere que en otro archivo … const resumen = require(‘./SummaryModule’) … y va a ser la misma instancia. Usted puede probar esto mediante la creación de un miembro de la variable y establecer su valor en un archivo, que se requiere y, a continuación, obtener su valor en otro archivo que requiere. Debe ser el valor que se ha establecido.
  8. 4

    Los únicos que están bien en JS, solo que no se necesita ser tan detallado.

    En el nodo si usted necesita un singleton, por ejemplo, para utilizar el mismo ORM/instancia de base de datos a través de varios archivos en el servidor de la capa, puedes rellenar la referencia a una variable global.

    Acaba de escribir un módulo que crea el mundial de var si no existe, entonces devuelve una referencia a eso.

    @allen-luce tenía razón con su nota de pie de página ejemplo de código copiado de aquí:

    singleton.getInstance = function(){
      if(global.singleton_instance === undefined)
        global.singleton_instance = new singleton();
      return global.singleton_instance;
    };
    
    module.exports = singleton.getInstance();

    pero es importante tener en cuenta que el uso de la new palabra clave es no necesario. Cualquier objeto antiguo, de la función, iife, etc. van a trabajar, no hay ninguna programación orientada a objetos vudú sucediendo aquí.

    puntos de bonificación si usted cierre de algunos obj dentro de una función que devuelve una referencia a él, y asegúrese de que la función de un mundial -, a continuación, incluso la reasignación de la variable global no darle una paliza a las instancias ya creadas a partir de ello – aunque esto es cuestionable utilidad.

    • usted no necesita nada de eso. usted puede hacer module.exports = new Foo() porque módulo.las exportaciones no se ejecutará de nuevo, a menos que haga algo realmente estúpido
    • Usted absolutamente NO debe depender de la implementación de efectos secundarios. Si usted necesita una sola instancia sólo el empate a un mundial, en el caso de la implementación de los cambios.
    • La respuesta anterior era también una falta de comprensión de la pregunta original como » debo usar singleton en JS o no el idioma de ellos innecesarios?’, lo que también parece ser un problema con muchas de las otras respuestas. Mantengo mi recomendación en contra del uso de la aplicación como un reemplazo para una adecuada explícita implementación de singleton.
  9. 1

    Mantenerlo simple.

    foo.js

    function foo() {
    
      bar: {
        doSomething: function(arg, callback) {
          return callback('Echo ' + arg);
        };
      }
    
      return bar;
    };
    
    module.exports = foo();

    A continuación, sólo

    var foo = require(__dirname + 'foo');
    foo.doSomething('Hello', function(result){ console.log(result); });
    • la pregunta es «son los únicos necesarios», no «¿cómo se escribe una»

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea