javascript - script - Convertir objetos Singleton JS para usar clases ES6
singleton javascript ejemplo (4)
Estoy usando ES6 con el Webpack es6-transpiler para mi artículo aquí: http://www.railsonmaui.com/blog/2014/10/02/integrating-webpack-and-the-es6-transpiler-into-an-existing-rails-project/
¿Tiene algún sentido convertir dos objetos Singleton para usar clases ES6?
import { CHANGE_EVENT } from "../constants/Constants";
var EventEmitter = require(''events'').EventEmitter;
var merge = require(''react/lib/merge'');
var _flash = null;
var BaseStore = merge(EventEmitter.prototype, {
emitChange: function() {
this.emit(CHANGE_EVENT);
},
/**
* @param {function} callback
*/
addChangeListener: function(callback) {
this.on(CHANGE_EVENT, callback);
},
/**
* @param {function} callback
*/
removeChangeListener: function(callback) {
this.removeListener(CHANGE_EVENT, callback);
},
getFlash: function() {
return _flash;
},
setFlash: function(flash) {
_flash = flash;
}
});
export { BaseStore };
Este es el archivo ManagerProducts.jsx que tiene un singleton que debería extenderse desde BaseStore.
/**
* Client side store of the manager_product resource
*/
import { BaseStore } from "./BaseStore";
import { AppDispatcher } from ''../dispatcher/AppDispatcher'';
import { ActionTypes } from ''../constants/Constants'';
import { WebAPIUtils } from ''../utils/WebAPIUtils'';
import { Util } from "../utils/Util";
var merge = require(''react/lib/merge'');
var _managerProducts = [];
var receiveAllDataError = function(action) {
console.log("receiveAllDataError %j", action);
WebAPIUtils.logAjaxError(action.xhr, action.status, action.err);
};
var ManagerProductStore = merge(BaseStore, {
getAll: function() {
return _managerProducts;
}
});
var receiveAllDataSuccess = function(action) {
_managerProducts = action.data.managerProducts;
//ManagerProductStore.setFlash({ message: "Manager Product data loaded"});
};
ManagerProductStore.dispatchToken = AppDispatcher.register(function(payload) {
var action = payload.action;
if (Util.blank(action.type)) { throw `Invalid action, payload ${JSON.stringify(payload)}`; }
switch(action.type) {
case ActionTypes.RECEIVE_ALL_DATA_SUCCESS:
receiveAllDataSuccess(action);
break;
case ActionTypes.RECEIVE_ALL_DATA_ERROR:
receiveAllDataError(action);
break;
default:
return true;
}
ManagerProductStore.emitChange();
return true;
});
export { ManagerProductStore };
No. No tiene sentido.
Aquí hay un ejemplo muy simple de un objeto singleton en es6:
let appState = {};
export default appState;
Si realmente desea utilizar una clase en su enfoque de singleton, recomendaría no usar "static", ya que es más confuso que bueno para un singleton, al menos para JS, y en su lugar, devolvería la instancia de la clase como un singleton como ...
class SomeClassUsedOnlyAsASingleton {
// implementation
}
export default new SomeClassUsedOnlyAsASingleton();
De esta manera, aún puede usar todas las cosas de clase que le gusta que ofrece JavaScript, pero reducirá la confusión, ya que IMO estática no es totalmente compatible con las clases de JavaScript de todos modos, ya que está en lenguajes escritos como c # o Java, ya que solo admite métodos estáticos a menos que simplemente lo falsifique y los adjunte directamente a una clase (en el momento de escribir este documento).
Para crear un patrón Singleton, use una sola instancia con clases ES6;
''use strict'';
import EventEmitter from ''events'';
class Single extends EventEmitter {
constructor() {
this.state = {};
}
getState() {
return this.state;
}
}
export default let single = new Single();
Actualización : Según la explicación de @Bergi, a continuación uno no es un argumento válido.
Esto funciona debido a (refiérase a Steven )
Puedes encontrar un ejemplo aquí ES6 Singleton .
Nota : este patrón se está utilizando en Flux Dispacher
Flujo : www.npmjs.com/package/flux
Ejemplo de Dispacher : github.com/facebook/flux/blob/master/examples/flux-todomvc/js/dispatcher/AppDispatcher.js#L16
Tuve que hacer lo mismo, así que aquí hay una forma simple y directa de hacer un singleton, una reverencia a singleton-classes-in-es6
(enlace original amanvirk.me/singleton-classes-in-es6 )
let instance = null;
class Cache{
constructor() {
if(!instance){
instance = this;
}
// to test whether we have singleton or not
this.time = new Date()
return instance;
}
}
let cache = new Cache()
console.log(cache.time);
setTimeout(function(){
let cache = new Cache();
console.log(cache.time);
},4000);
Ambas llamadas cache.time
deben imprimir el mismo cache.time
(Singleton)
Yo diría que los singletons (las clases que administran su propia vida de singleton) son innecesarios en cualquier idioma. Eso no quiere decir que el tiempo de vida de singleton no sea útil, solo que prefiero que otra cosa que no sea la clase administre el tiempo de vida de un objeto, como un contenedor DI.
Dicho esto, el patrón Singleton PUEDE aplicarse a las clases de JavaScript, tomando prestado el patrón "SingletonEnforcer" que se usó en ActionScript. Puedo ver querer hacer algo como esto cuando se transfiere una base de código existente que usa singletons a ES6.
En este caso, la idea es que singleton
instancia de singleton
estática privada (a través de un símbolo no expuesto), con un captador de instance
estático público. Luego, restringe el constructor a algo que tenga acceso a un símbolo especial de singletonEnforcer
que no esté expuesto fuera del módulo. De esa manera, el constructor falla si alguien que no sea el singleton intenta "renovarlo". Se vería algo como esto:
const singleton = Symbol();
const singletonEnforcer = Symbol()
class SingletonTest {
constructor(enforcer) {
if(enforcer != singletonEnforcer) throw "Cannot construct singleton";
}
static get instance() {
if(!this[singleton]) {
this[singleton] = new SingletonTest(singletonEnforcer);
}
return this[singleton];
}
}
export default SingletonTest
Entonces puedes usarlo como cualquier otro singleton:
import SingletonTest from ''singleton-test'';
const instance = SingletonTest.instance;