在需要其他模块之前等待异步操作

wait for an async operation before requiring other modules

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

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

示例:

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

    GLOBAL.obj = data;
});

require('./module.js');

module.js

obj.someFunction();

是的,只要遵循异步编程的第一条规则。依赖于回调发生的事情必须在该回调中执行。由于您的 require 取决于异步中设置的变量,因此您只能在其中使用 require

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

    GLOBAL.obj = data;
    require('./module.js');
});

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

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

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

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

  • 使该函数成为模块的单一导出。它充当工厂函数并为该模块中的所有其他函数创建上下文。它应该 return 无论之前导出的模块是什么。

例子

// 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(){}};