Подтвердить что ты не робот

Преобразование объектов SingleSt JS для использования классов ES6

Я использую ES6 с Webpack es6-transpiler в моей статье здесь: http://www.railsonmaui.com/blog/2014/10/02/integrating-webpack-and-the-es6-transpiler-into-an-existing-rails-project/

Есть ли смысл конвертировать два объекта Singleton для использования классов 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 };

Это файл ManagerProducts.jsx, который имеет один синглтон, который должен простираться от 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 };
4b9b3361

Ответ 1

Я бы сказал, что одиночные игры (классы, которые управляют своим собственным временем жизни) не нужны ни на одном языке. Это не означает, что одноэлементное время жизни не полезно, просто я предпочитаю, чтобы что-то, кроме класса, управляло временем жизни объекта, например, контейнера DI.

При этом одноэлементный шаблон CAN может применяться к классам JavaScript, заимствуя шаблон "SingletonEnforcer", который использовался в ActionScript. Я вижу, что хочу сделать что-то подобное при переносе существующей базы кода, которая использует синглтоны в ES6.

В этом случае идея состоит в том, что вы делаете статический экземпляр singleton с приватным (через un выставленный Symbol) с открытым статическим instance getter. Затем вы ограничиваете конструктор тем, что имеет доступ к специальному символу singletonEnforcer, который не отображается вне модуля. Таким образом, конструктор терпит неудачу, если кто-то, кроме синглтона, попытается "обновить" его. Он будет выглядеть примерно так:

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

Затем вы можете использовать его, как и любой другой синглтон:

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

Ответ 2

Нет. Не имеет смысла.

Вот действительно простой пример одиночного объекта в es6:

let appState = {};
export default appState;

Я использую этот подход в своем коде для общего состояния через модули. Не знаете, почему вы должны преобразовать его в класс только потому, что? Одиночный по его определению статически используется. Наличие того, чтобы код не использовать класс в качестве экземпляра класса, должен быть большим ключом, чтобы этого не делать.

Синглеты очень полезны для управления состоянием или когда экземпляры не имеют смысла использовать какую-либо библиотеку утилиты. Я не вижу причин не использовать их, если это необходимо.

Это крошечный пример того, как программисты стремятся к тому, чтобы сконструировать или масштабировать все до своего даже необходимого, и это огромная проблема в моем опыте, в результате чего проекты заканчиваются в некоторых случаях из-за отсутствия производительности. Потратьте свое время на приложение, а не на интеллектуальный рывок.

Ответ 3

Я должен был сделать то же самое, поэтому вот простой и прямой способ сделать синглтон, curtsy to 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);

Оба вызова console.log должны печатать один и тот же cache.time (Singleton)

Ответ 4

Чтобы создать шаблон Singleton, используйте один экземпляр с классами ES6;

'use strict';

import EventEmitter from 'events';

class Single extends EventEmitter {
    constructor() {
        this.state = {};
    }

    getState() {
        return this.state;
    }

}

export default let single = new Single();

Обновить. Согласно объяснению @Bergi, ниже один не является допустимым аргументом.

Это работает из-за (см. Steven)

> Если я правильно понимаю реализации CommonJS + в браузере, > вывод модуля кэшируется, поэтому экспорт по умолчанию нового MyClass() будет > привести к чему-то, что ведет себя как одиночный (только один > экземпляр этого класса будет когда-либо существовать на процесс/клиент в зависимости от > env он работает). Дел >

Здесь вы можете найти пример ES6 Singleton.

Примечание: этот шаблон используется в Flux Dispacher

Flux: www.npmjs.com/package/flux

Пример Dispacher: github.com/facebook/flux/blob/master/examples/flux-todomvc/js/dispatcher/AppDispatcher.js#L16

Ответ 5

Альтернативный ответ

Классы ES6 поддерживают "статическое" ключевое слово, поэтому, по существу, вы можете создать класс и по самому его определению, используя статические члены, чтобы он имел возможности singleton по дизайну.

class MyClass {

  static instanceCount = 0;

  constructor() {
    MyClass.instanceCount++; 
  }

  static getInstanceCount() {
    // "this" refers to static members when used within a static method
    return this.instanceCount;
  }

}

Таким образом вы получаете все функциональные возможности класса. Вы можете хранить глобальные данные внутри них другими словами, но более структурированным способом.