Sunday, May 12, 2024
158
rated 0 times [  163] [ 5]  / answers: 1 / hits: 44056  / 10 Years ago, sun, october 5, 2014, 12:00:00

I'm using ES6 with the Webpack es6-transpiler per my article here: http://www.railsonmaui.com/blog/2014/10/02/integrating-webpack-and-the-es6-transpiler-into-an-existing-rails-project/



Does it make any sense to convert two Singleton objects to use ES6 Classes?



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 };


This is file ManagerProducts.jsx that has a singleton that should extend from 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 };

More From » ecmascript-6

 Answers
19

I'd argue that singletons (classes that manage their own singleton lifetime) are unnecessary in any language. That is not to say that singleton lifetime is not useful, just that I prefer that something other than the class manage the lifetime of an object, like a DI container.



That being said, the singleton pattern CAN be applied to JavaScript classes, borrowing the SingletonEnforcer pattern that was used in ActionScript. I can see wanting to do something like this when porting an existing code base that uses singletons into ES6.



In this case, the idea is that you make a private (via an un exposed Symbol) static singleton instance, with a public static instance getter. You then restrict the constructor to something that has access to a special singletonEnforcer symbol that is not exposed outside of the module. That way, the constructor fails if anyone other than the singleton tries to new it up. It would look something like this:



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


Then you can use it like any other singleton:



import SingletonTest from 'singleton-test';
const instance = SingletonTest.instance;

[#69234] Thursday, October 2, 2014, 10 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
reina

Total Points: 241
Total Questions: 82
Total Answers: 94

Location: New Caledonia
Member since Thu, Mar 23, 2023
1 Year ago
reina questions
;