【问题标题】:Using object from different module使用来自不同模块的对象
【发布时间】:2015-08-30 08:55:45
【问题描述】:

我有以下代码,它是解析对象,并像下面一样为其提供吸气剂,这是有效的,问题是我想从不同的模块访问这个对象并避免再次解析,我该怎么做没有定义全局变量?

var ymlParser = require('yamljs');

function ymlParse(src) {
    if (!(this instanceof ymlParse)) return new ymlParse(src);
    this.data = ymlParser.parse(src);
}

ymlParse.prototype = {
    getA: function () {
        return this.data.default_A;
    },

    getB: function () {
        return this.data._B;
    }
};

module.exports = ymlParse;

假设我想从模块 A 访问 A 和从模块 B 访问 B,当我调用 getB 时,我怎么能不再次发送 src通过 src...

【问题讨论】:

    标签: javascript node.js module require


    【解决方案1】:

    您可以使用记忆模式 - http://addyosmani.com/blog/faster-javascript-memoization/。在其他答案中实施的一个问题不是散列参数。所以你应该有这样的东西:

    var ymlParser = require('yamljs');
    
    function ymlParse(src) {
      var hash = JSON.stringify(src);
    
      if (!(this instanceof ymlParse)) return new ymlParse(src);
      if (this.cache[hash]) {
        this.data = this.cache[hash];
      } else {
        this.data = ymlParser.parse(src);
        this.cache[hash] = this.data;
      }
    }
    
    ymlParse.prototype = {
      cache: {},
    
      getA: function () {
        return this.data.default_A;
      },
    
      getB: function () {
        return this.data._B;
      }
    };
    
    module.exports = ymlParse;
    

    仔细查看 JSON.stringify 方法。您必须在此处实现散列算法,将散列与 src 数据关联为唯一标识符。通常是 JSON.stringify 但你可以使用自己的。

    或另一种功能风格的解决方案:

    var _ = require('lodash');
    var ymlParser = require('yamljs');
    
    function ymlParse(src) {
      var result = ymlParser.parse(src);
    
      return {
        getA: function() {
          return result.default_A;
        },
        getB: function() {
          return result._B;
        }
      };
    }
    
    module.exports = _.memoize(ymlParse);
    

    用法相同,你只需像平常的函数一样调用导出的函数。

    【讨论】:

    • 谢谢,但我的问题是,当我调用 A 时,我传递了 src,而当我调用 B 时,我没有传递给它的 src,有办法克服它吗?
    • 对不起,当我试图从其他模块获取值时,缓存是空的,但也许我以错误的方式调用它,我应该如何为不同的模块调用它假设提供src 和第二个不是?
    • 没有参数怎么调用函数?您做错了什么,因此请尝试在不拆分为模块的情况下解决此问题。
    • 以函数式样式为例,您拥有可以记住计算结果的函数。如果您使用 src 调用该函数,它会记住它并将结果存储在缓存中。但是如果你根本没有 src 怎么办?
    • 假设我只需要解析节点应用程序中的一个文件,因此使用 src 调用第一个调用者,然后解析数据,其他模块无需发送即可获得所需的属性src,..因为数据已经解析并为所有模块提供服务
    【解决方案2】:

    您可以在 ymlParse 类中进行缓存(它的设计类似于类,不是吗?)。 只需存储src 对象和解析结果。如果ymlParse 将使用缓存的src 执行,则只返回存储的结果而不进行解析。

    尝试像这样更改您的代码:

    var ymlParser = require('yamljs');
    
    function ymlParse(src) {
        if (!(this instanceof ymlParse)) return new ymlParse(src);
        if (this.cache[src]) {
            this.data = this.cache[src];
        } else {
            this.data = ymlParser.parse(src);
            this.cache[src] = this.data;
        }
    }
    
    ymlParse.prototype = {
        cache: {},
    
        getA: function () {
            return this.data.default_A;
        },
    
        getB: function () {
            return this.data._B;
        }
    };
    
    module.exports = ymlParse;
    

    请注意,我没有使用 this.data 对象的深层副本。如果它不是只读的,可能会导致一些问题。

    【讨论】:

    • 谢谢,我试了一下,但是当我从模块 B 访问时,this.cache[src] 是空的,所以再次调用解析......也许我把这叫错了?我应该如何调用它(函数)?
    • 请记住我需要从两个不同的模块调用它
    • 有点奇怪。我不确定,但据我所知,每个模块只执行一次,在第一次需要时,其他时候只是将module.exports 返回给其他人。因此,基于此,您的所有模块都应该具有解析器的 module.exports 的相同实例,并且它是原型。
    • 尝试找出 - 您的模块是否只执行一次或多次。您可以通过在其开头添加 console.log 来做到这一点。
    • 谢谢,但我的问题是,当我调用 A 时,我传递了 src,而当我调用 B 时,我没有传递给它的 src,有办法克服它
    猜你喜欢
    • 2014-01-27
    • 1970-01-01
    • 2013-12-06
    • 1970-01-01
    • 2018-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多