【问题标题】:wait for an async operation before requiring other modules在需要其他模块之前等待异步操作
【发布时间】:2015-09-06 22:07:59
【问题描述】:

在我的 main.js 中,我正在异步读取文件。加载文件后,我在 GLOBAL 命名空间中设置一些对象并在我的 required 模块中使用它们(是否使用 GLOBAL 命名空间是另一回事,无论如何我都在使用它)。

我的required 模块立即期望该变量在加载时存在。那么如何让它等到 main.js 中的文件读取完成?我只是在readFile 的回调中需要模块吗?还是有更好的方法?

示例:

fs.readFile('./file', function (data) {
    // do something

    GLOBAL.obj = data;
});

require('./module.js');

模块.js

obj.someFunction();

【问题讨论】:

  • 仅供参考,这是一个糟糕的设计模式。如果一个模块需要一些外部状态,那么该模块应该公开一个构造函数,并且当状态可用时你应该调用该构造函数。然后,您可以随时require() 模块,并在您拥有该状态时通过调用构造函数(并将该状态传递给构造函数)来完成对其的初始化。
  • 太棒了!我期待这样的建议。我不是很高兴requireing 这样的模块。谢谢,我会遵循这个模式。

标签: javascript node.js node-modules


【解决方案1】:

您不喜欢该解决方案的直觉是可以理解的。 (你的胃是对的)。清理它的正确方法(你应该花时间——未来——你会感谢你的):

  • 浏览十个模块中的每一个
  • 每一个都要遍历它导出的所有函数
  • 为每个函数找出它们实际上依赖的全局变量。
  • 将这些作为参数添加到函数中。 如果他们现在有很多论据,请考虑将它们分组为对象,创建有用的模型。

如果一堆函数都依赖同一套变量,也可以考虑创建一个工厂函数

  • 创建一个将以前的全局变量作为参数的函数,并将模块的所有代码包装到该函数中。

  • 将该函数作为模块的单一导出。它充当工厂函数并为该模块中的所有其他函数创建上下文。它应该返回之前导出的任何模块。

例子

// DB used to be a global
module.exports = function(DB) {
    function getUser(user, cb) {
        DB.get('user', db);
    }
    return {getUser: getUser};
};

然后你可以像这样使用它:

var module = require('module')(DB);
module.getUser(myUser, function(){}};

【讨论】:

    【解决方案2】:

    是的,只需遵循异步编程的规则 #1。依赖于回调发生的东西必须在该回调中执行。由于您的require 依赖于异步设置的变量,因此您只能在其中使用您的require

    fs.readFile('./file', function (data) {
        // do something
    
        GLOBAL.obj = data;
        require('./module.js');
    });
    

    【讨论】:

    • 我明白了。但是有几十个模块依赖于GLOBAL.obj,我应该require 都在回调中吗?我想到了这一点,但想知道是否有更好的解决方案。
    • 没有更好的解决方案。如果十个模块依赖于你的回调中发生的某些事情,那么它们就不能在回调之外被要求(或使用)。
    猜你喜欢
    • 1970-01-01
    • 2017-11-14
    • 2021-02-16
    • 1970-01-01
    • 2015-06-13
    • 1970-01-01
    • 2019-09-30
    • 2016-10-17
    • 1970-01-01
    相关资源
    最近更新 更多