Почему у моего Singleton-модуля два экземпляра? - PullRequest
0 голосов
/ 27 мая 2019

Проблема

Я пытаюсь создать синглтон, в котором хранится информация, доступ к которой возможен только с помощью сеттеров и геттеров.Мне нравится, чтобы мой код был как можно более коротким и чистым, поэтому я всегда ищу кратчайший способ написания вещей.Хотя это работает в большинстве мест, в других я склонен создавать некоторые не объяснимые (для меня) ошибки.

Итак, при импорте моего модуля для тестирования я использую:

const { ports, instance: activeConfig } = require('./activeConfig')

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

Несколько вещей, которые я наблюдал:

  1. Когда я запускаю activeConfig.ports мой геттерактивирован.Я вижу это до того, как запишем результат 1, 2 и 3.
  2. Когда я запускаю только ports, мой геттер НЕ активирован.Я вижу из результатов журнала 1a, 2a и 3a, что внутри синглтона ничего не запускается.Но я все еще получаю результаты.
  3. Когда я устанавливаю новые значения, я вижу внутри синглтона мое значение для _myPorts меняется.Результат для обоих методов также, как я и ожидал.

Однако после сброса значений это поведение больше не остается согласованным.activeConfig.ports дает ожидаемый результат, ports - нет.Я не уверен, откуда журнал 3a получает этот результат и почему он отличается от результата журнала 3.

Я, очевидно, создал некоторую нестабильность, но мои навыки JavaScript не достаточно сильны, чтобы точно определить проблему.Я пытался найти все варианты «JavaScript Singleton Getter Export», но, похоже, не могу найти пример, который бы охватил мой конкретный вариант использования.

Если бы кто-нибудь мог помочь мне исправить мой код, он был бы очень признателен.Кроме того, такие мелочи, как правильная терминология или ссылки на расширенные примеры, были бы очень полезны.:)

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

Я не ищу обходные пути, такие как:

const activeConfig = require('./activeConfig')
const ports = activeConfig.ports

или

const ports = require('./activeConfig').ports

Для этого потребуется одна строка на получателя, и я пытаюсь избежать этого точноситуации.(Особенно с 10+ получателями)

Я бы очень хотел узнать, есть ли правильный способ сделать это.:)

Код

'use strict'
let activeConfig = (function () {
  const _defPorts = {
    http: 80,
    https: 443,
    secure: false
  }

  let _myPorts = {..._defPorts}

  let _setPorts = function (value) {
    console.log('SP->', _myPorts)
    if (value) {
      Object.keys(value).forEach((key) => {
        if (typeof _myPorts[key] !== 'undefined') {
          _myPorts[key] = value[key]
        }
      })
    }
    console.log('SP=>', _myPorts)
  }

  let _resetConfig = function () {
      console.log('RC->', _myPorts)
      _myPorts = {..._defPorts}
      console.log('RC=>', _myPorts)
    }


  return {
    setPorts: _setPorts,
    resetConfig: _resetConfig,
    get instance() {
      return activeConfig 
    },
    get ports() {
      console.log('GP->', _myPorts)
      return _myPorts
    },
    set ports(value) {
      return _setPorts(value)
    }
  }
})()
module.exports = activeConfig

Код теста

'use strict'
const {
    ports,
    instance: activeConfig
} = require('./activeConfig')

console.log('1 ->', activeConfig.ports)
console.log('1a->', ports)
activeConfig
    .setPorts({
        secure: true,
        http: 8080
    })

console.log('2 ->', activeConfig.ports)
console.log('2a->', ports)
console.log('RESET')
activeConfig.resetConfig()
console.log('3 ->', activeConfig.ports)
console.log('3a->', ports)

Журнал

GP-> { http: 80, https: 443, secure: false }
GP-> { http: 80, https: 443, secure: false }
1 -> { http: 80, https: 443, secure: false }
1a-> { http: 80, https: 443, secure: false }
SP-> { http: 80, https: 443, secure: false }
SP=> { http: 8080, https: 443, secure: true }
GP-> { http: 8080, https: 443, secure: true }
2 -> { http: 8080, https: 443, secure: true }
2a-> { http: 8080, https: 443, secure: true }
RESET
RC-> { http: 8080, https: 443, secure: true }
RC=> { http: 80, https: 443, secure: false }
GP-> { http: 80, https: 443, secure: false }
3 -> { http: 80, https: 443, secure: false }
3a-> { http: 8080, https: 443, secure: true }

1 Ответ

1 голос
/ 27 мая 2019

Деструктуризация объекта - это просто синтаксический сахар вокруг доступа к собственности:

 const { port } = obj;
 // equals
 const port = obj.port;

поэтому во время деструкции вы получаете доступ к геттеру. Изменение port изменяет локальную переменную. Он не отражается на объекте и, следовательно, не вызывает установщика.

Нет реального способа использовать геттеры / сеттеры таким образом (хорошо, давайте забудем о with).

Вместо этого вы можете вручную запускать нереальные сеттеры:

  const obj = {
    port: { set(_v) { return this._v = _v; }, get() { return this._v; } }
  };

 const { port } = obj;
 port.set(10);
...