【问题标题】:Why does my Singleton Module seem to have two instances?为什么我的单例模块似乎有两个实例?
【发布时间】:2019-05-27 15:40:44
【问题描述】:

问题

我正在尝试创建一个 Singleton 来存储只能通过 Setter 和 Getter 访问的信息。我喜欢让我的代码尽可能简短和干净,所以我一直在寻找最短的编写方式。虽然这在大多数地方都有效,但在其他地方,我往往会产生一些(对我而言)无法解释的错误。

所以,.. 在导入我的模块进行测试时,我使用:

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

ports 应该是我的 Getter。我想避免在可能的情况下总是写出activeConfig.ports。在我尝试重置我的值之前,我认为大部分情况下这在我的测试中是有效的。

我观察到的一些事情:

  1. 当我运行activeConfig.ports 时,我的getter 被激活。我可以在日志结果 1、2 和 3 之前看到这一点。
  2. 当我只运行ports 时,我的getter 没有被激活。我可以从日志结果 1a、2a 和 3a 中看到单例内部没有运行任何内容。但我仍然得到了结果。
  3. 当我设置一个新值时,我可以在 Singleton 中看到我的 _myPorts 值确实发生了变化。这两种方法的结果也符合我的预期。

但是,在我重置我的值后,这种行为不再保持一致。虽然activeConfig.ports 提供了预期的结果,但ports 没有。我不确定日志 3a 从哪里得到这个结果以及为什么它与日志结果 3 不同。

我显然已经内置了某种不稳定因素,但我的 JavaScript 技能还不足以查明问题所在。我尝试搜索“JavaScript Singleton Getter Export”的所有变体,但似乎找不到涵盖我的特定用例的示例。

如果有人可以帮助我修复我的代码,将不胜感激。此外,像正确的术语或高级示例的链接这样的小东西真的会很感激。 :)

我的主要关注点是能够在单个 require 命令中导入 getter!
我已经简化了这个例子,但我希望能够用 x 个吸气剂来做到这一点。

我不是在寻找解决方法,例如:

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 }

【问题讨论】:

    标签: javascript node.js singleton getter-setter


    【解决方案1】:

    对象解构只是属性访问的语法糖:

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

    因此,在您解构时,您确实可以访问 getter。更改 port 会更改局部变量。它不会反射到对象上,因此不会触发 setter。

    没有真正的方法以这种方式使用 getter / setter(好吧,让我们忘记with)。

    相反,您可以手动触发虚幻设置器:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-08
      • 2016-06-10
      • 2023-03-21
      • 1970-01-01
      • 2012-11-17
      相关资源
      最近更新 更多