Konwertowanie obiektów Singleton JS na klasy ES6
Używam ES6 z Webpack es6-transpiler na mój artykuł tutaj: http://www.railsonmaui.com/blog/2014/10/02/integrating-webpack-and-the-es6-transpiler-into-an-existing-rails-project/
Czy konwersja dwóch obiektów Singleton na klasy ES6 ma sens?
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 };
To jest file ManagerProducts.jsx, który ma singleton, który powinien rozciągać się od 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 };
4 answers
Argumentowałbym, że singletony (klasy, które zarządzają własnym życiem Singletona) są niepotrzebne w każdym języku. Nie oznacza to, że singleton lifetime nie jest przydatny, tylko, że wolę, aby coś innego niż klasa zarządzała życiem obiektu, jak kontener DI.
To powiedziawszy, wzór Singletona może być stosowany do klas JavaScript, zapożyczając wzór "SingletonEnforcer", który został użyty w ActionScript. Widzę chęć zrobienia czegoś takiego, kiedy portowanie istniejącej bazy kodu używającej singletonów do ES6.
W tym przypadku idea polega na tym, że tworzy się prywatną (za pomocą nieeksponowanego symbolu) statyczną instancję singleton
, z publicznym statycznym getterem instance
. Następnie ograniczasz konstruktor do czegoś, co ma dostęp do specjalnego symbolu singletonEnforcer
, który nie jest eksponowany poza modułem. W ten sposób konstruktor zawiedzie, jeśli ktoś inny niż singleton spróbuje go "zmienić". Wyglądałoby to mniej więcej tak:
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
Wtedy możesz używaj go jak każdy inny singleton:
import SingletonTest from 'singleton-test';
const instance = SingletonTest.instance;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-24 12:36:03
Nie. To nie ma sensu.
Oto bardzo prosty przykład obiektu singleton w es6:
let appState = {};
export default appState;
Jeśli naprawdę chcesz użyć klasy w podejściu singleton, zalecam, aby nie używać "static", ponieważ jest to bardziej mylące niż dobre dla Singletona przynajmniej dla JS i zamiast tego zwracać instancję klasy jako singleton jak tak...
class SomeClassUsedOnlyAsASingleton {
// implementation
}
export default new SomeClassUsedOnlyAsASingleton();
W ten sposób możesz nadal używać wszystkich rzeczy klasowych, które lubisz, które oferuje JavaScript, ale zmniejszy to zamieszanie jako IMO static nie jest w pełni wspierany w klasach JavaScript, jak to jest w typowanych językach, takich jak c# lub Java, ponieważ obsługuje tylko statyczne metody, chyba że po prostu fałszujesz i dołączasz je bezpośrednio do klasy(w momencie pisania tego tekstu).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-11 17:07:29
Musiałem zrobić to samo, więc oto prosty i bezpośredni sposób na wykonanie singletonu, do singleton-classes-in-es6
(oryginalny link http://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);
Oba wywołania console.log
powinny drukować to samo cache.time
(Singleton)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-23 20:50:55
W celu stworzenia wzorca Singletona Użyj pojedynczej instancji z klasami ES6;
'use strict';
import EventEmitter from 'events';
class Single extends EventEmitter {
constructor() {
this.state = {};
}
getState() {
return this.state;
}
}
export default let single = new Single();
Update: zgodnie z wyjaśnieniem @ Bergi, poniżej jeden nie jest prawidłowym argumentem.
to działa z powodu (patrz Steven)
Przykład można znaleźć tutaj ES6 Singleton.
Uwaga : ten wzór jest używany w Flux Dispacher
Flux: www.npmjs.com/package/flux
Przykład Dispachera: github.com/facebook/flux/blob/master/examples/flux-todomvc/js/dispatcher/AppDispatcher.js#L16
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-18 13:59:47