node javascript requirejs

javascript - node - requirejs download



Inyección de Dependencia con RequireJS (3)

¿Cuánto puedo estirar RequireJS para proporcionar inyección de dependencia para mi aplicación? Como ejemplo, digamos que tengo un modelo que quiero ser singleton. No es un singleton en una instancia de getInstance () de autoaplicación, sino un singleton forzado por contexto (una instancia por "contexto"). Me gustaría hacer algo como ...

require([''mymodel''], function(mymodel) { ... }

Y tenga mymodel sea una instancia de la clase MyModel. Si tuviera que hacer esto en múltiples módulos, me gustaría que mymodel sea la misma instancia compartida.

He hecho esto con éxito haciendo que el módulo mymodel sea así:

define(function() { var MyModel = function() { this.value = 10; } return new MyModel(); });

¿Este tipo de uso se espera y es común o estoy abusando de RequireJS? ¿Hay alguna forma más adecuada de realizar la inyección de dependencia con RequireJS? Gracias por tu ayuda. Todavía estoy tratando de entender esto.


No es un singleton en una instancia de getInstance () de autoaplicación, sino un singleton forzado por contexto (una instancia por "contexto").

Lo recomendaría solo para objetos estáticos. Está perfectamente bien tener un objeto estático como módulo que carga utilizando en los bloques requerir / definir. A continuación, crea una clase con solo propiedades y funciones estáticas. Entonces tiene el equivalente del objeto matemático que tiene constantes como PI, E, SQRT y funciones como round (), random (), max (), min (). Ideal para crear clases de utilidad que se pueden inyectar en cualquier momento.

En lugar de esto:

define(function() { var MyModel = function() { this.value = 10; } return new MyModel(); });

Lo cual crea una instancia, usa el patrón para un objeto estático (uno donde los valores son siempre los mismos ya que el Objeto nunca llega a ser instanciado):

define(function() { return { value: 10 }; });

o

define(function() { var CONSTANT = 10; return { value: CONSTANT }; });

Si desea pasar una instancia (el resultado de usar un Módulo que ha devuelto un nuevo MyModel ();), entonces, dentro de una función de inicialización, pase una variable que capture el estado / contexto actual o pase el Objeto que contiene información sobre estado / contexto que sus módulos necesitan saber.


Esto no es realmente inyección de dependencia, sino ubicación del servicio: los otros módulos solicitan una "clase" mediante una "clave" de cadena, y recuperan una instancia de la misma que el "localizador de servicios" (en este caso, RequireJS) se ha conectado a proporcionar para ellos.

La inyección de dependencias implicaría devolver el constructor de MyModel , es decir, return MyModel , luego en una raíz de composición central inyectando una instancia de MyModel en otras instancias. He reunido una muestra de cómo funciona esto aquí: https://gist.github.com/1274607 (también se cita a continuación)

De esta forma, la raíz de la composición determina si se distribuye una sola instancia de MyModel (es decir, si tiene un alcance único) o nuevas para cada clase que lo requiera (ámbito de la instancia) o algo intermedio. Esa lógica no pertenece ni a la definición de MyModel ni a las clases que solicitan una instancia de ella.

(Nota al wire.js : aunque no lo he usado, wire.js es un contenedor de inyección de dependencias completo para JavaScript que se ve muy bien).

No necesariamente está abusando de RequireJS utilizándolo como lo hace, aunque lo que está haciendo parece un poco indirecto, es decir, declarar una clase que devolver una nueva instancia de la misma. ¿Por qué no solo hacer lo siguiente?

define(function () { var value = 10; return { doStuff: function () { alert(value); } }; });

La analogía que puede estar perdiendo es que los módulos son equivalentes a "espacios de nombres" en la mayoría de los otros lenguajes, aunque sean espacios de nombres a los que pueda adjuntar funciones y valores. (Por lo tanto, más como Python que Java o C #). No son equivalentes a las clases, aunque como ha mostrado, puede hacer que las exportaciones de un módulo sean iguales a las de una instancia de clase determinada.

De modo que puede crear singletons adjuntando funciones y valores directamente al módulo, pero esto es como crear un singleton usando una clase estática: es altamente inflexible y generalmente no es la mejor práctica. Sin embargo, la mayoría de las personas trata sus módulos como "clases estáticas", ya que la arquitectura adecuada de un sistema para la inyección de dependencias requiere una gran cantidad de pensamiento desde el principio, que en realidad no es la norma en JavaScript.

Aquí está https://gist.github.com/1274607 línea:

// EntryPoint.js define(function () { return function EntryPoint(model1, model2) { // stuff }; }); // Model1.js define(function () { return function Model1() { // stuff }; }); // Model2.js define(function () { return function Model2(helper) { // stuff }; }); // Helper.js define(function () { return function Helper() { // stuff }; }); // composition root, probably your main module define(function (require) { var EntryPoint = require("./EntryPoint"); var Model1 = require("./Model1"); var Model2 = require("./Model2"); var Helper = require("./Helper"); var entryPoint = new EntryPoint(new Model1(), new Model2(new Helper())); entryPoint.start(); });


Si habla en serio sobre DI / IOC, podría estar interesado en wire.js: wire.js

Usamos una combinación de reubicación de servicio (como describe Domenic, pero usando curl.js en lugar de RequireJS) y DI (usando wire.js). La reubicación del servicio es muy útil cuando se usan objetos simulados en arneses de prueba. DI parece la mejor opción para la mayoría de los otros casos de uso.