我们可以不使用Sync方法做任何事情,或者在某些情况下,我们必须在node.js中使用Sync方法吗?

时间:2014-02-05 02:27:08

标签: javascript node.js asynchronous functional-programming require

例如,我有 app.js 来加载一个模块对象:M加载(require)一个文件:_core.js,然后M的属性是通过在目录下加载(require)文件来添加的:./Project_Functions/

var Project_FunctionsDIR = './Project_Functions/';
var Project_coreFile = '_core.js';

var M = require(Project_FunctionsDIR + Project_coreFile);

require("fs")
  .readdir(Project_FunctionsDIR,
    function(err, files)
    {
      files.forEach(function(file)
      {
        if (file !== Project_coreFile)
        {
          var name = file.split('.js')[0]; 
          var filepath = Project_FunctionsDIR + file;
          M[name] = require(filepath); 
        }
      });
    });
console.log('module.exports');
module.exports = M;

此处,构造的moduleObject:Mmodule.exports导出。

请注意fs.readdir是异步的,因此在module.exports = M;中构建 M属性之前,{em}评估app.js

现在,我想在 M 中测试此对象test.js

var expect = require('chai').expect;

var M = require('./app.js');
//........

var M = require('./app.js');行,评估app.js,表示在构建整个属性之前导出M对象

事实上,我在setTimeout回调中插入了fs.readdir,显然测试失败,M对象尚未就绪。

首先,我认为module.exports = M;应放在fs.readdir回调中,但如果我这样做,现在var M = require(Project_FunctionsDIR + Project_coreFile);部分失败,可能是因为module.exports = M;没有暴露正确阅读。

是的,这可以通过使用fs.readdirSync来解决,实际上,当我遇到这类问题时我一直在这样做,但是,我总是觉得使用节点同步方法感到不舒服,而是试图寻找一个更智能的解决方法。

所以,这是我的问题;可以通过不使用Sync方法来解决这个问题吗?还是不可能?

此外,我想更多地询问一下。

我们可以在不使用Sync方法的情况下执行任何操作,或者在某些情况下,我们必须使用node.js中的同步方法吗?

在函数式编程方案中,如果可能,应避免使用Sync方法,因为Sync概念取决于非函数(回调)但时间

谢谢你的想法。


编辑:

我刚刚在这里找到了一个相关主题: Asynchronous initialization of Node.js module

结论是我们必须使用Sync方法来对应Sync方法。在这种情况下,require是同步方法。

2 个答案:

答案 0 :(得分:0)

node.js使用CommonJS模块模式,根据定义,在加载时同步导出其公开的对象。您尝试做的事情不可能是异步的,尽管您可以通过将其他文件公开到“主”导出中来实现。如果要从一个对象动态公开目录中的所有文件,只需使用同步readdir,它只会在启动时执行。

答案 1 :(得分:0)

一种常见模式是模块公开异步initialize方法,该方法执行异步工作。对于您的模块,它看起来像这样:

var Project_FunctionsDIR = './Project_Functions/';
var Project_coreFile = '_core.js';

var M = require(Project_FunctionsDIR + Project_coreFile);

M.initialize = function(next) {
  require("fs")
  .readdir(Project_FunctionsDIR,
    function(err, files)
    {
      files.forEach(function(file)
      {
        if (file !== Project_coreFile)
        {
          var name = file.split('.js')[0]; 
          var filepath = Project_FunctionsDIR + file;
          M[name] = require(filepath); 
        }
      });
      next();
    });
}
module.exports = M;

然后你可以用:

进行测试
var M = require('./app.js');
M.initialize(function() {
  //........
}

这是一个有用的模式,因为许多异步方法没有同步版本,它允许您并行运行许多这些异步initialize,大大减少了较大应用程序的启动时间。