Node.js module.exports 不导出整个对象

Posted

技术标签:

【中文标题】Node.js module.exports 不导出整个对象【英文标题】:Node.js module.exports not exporting the whole object 【发布时间】:2015-12-13 11:52:30 【问题描述】:

我正在尝试将 sequelizejs 与 express 一起使用。模型被组织到多个目录中。

Users(directory)

users.js
profile.js
...

Articles

article.js
comments.js
...

我已修改 sequelize-express 示例以循环遍历子目录并使用 Promise 导入模型。

sequelize_init.js

'use strict';

var fs = require('fs'),
path = require('path'),
_ = require('lodash'),
config = require('./auth-config'),
Sequelize = require('sequelize'),
glob = require('glob'),
Q = require('q'),
db = ;

var sequelize;

function getGlobbedModels() 
    var deferred = Q.defer();
    glob('./config/sequelize/models/**/*.js', function(err, files) 
        if(err)
            deferred.reject('Glob Error' + err);
        else
            deferred.resolve(files);
    );
    return deferred.promise;


function importModels(models)
    var deferred = Q.defer();
    for (var i = models.length - 1; i >= 0; i--) 
        if(!i) 
            deferred.resolve('Successfully Required');
        
        var model = sequelize.import(path.resolve(models[i]));
        db[model.name] = model;
    
    return deferred.promise;


function associateModels(resp) 
    var deferred = Q.defer();
    var models = Object.keys(db);
    for (var i = models.length - 1; i >= 0; i--) 
        if(!i) 
            deferred.resolve();
        
        if(db[models[i]].options.hasOwnProperty('associate')) 
            db[models[i]].options.associate(db);
        
    
    return deferred.promise;


function synchronize() 
    // Synchronizing any model changes with database. 
    sequelize
        .sync(
            force: process.env.FORCE_DB_SYNC
        )
        .then(function () 
            console.info('Database synchronized');
        ).catch(function (err) 
            console.error('An error occurred: ', err);
        );


if(process.env.NODE_ENV === 'PRODUCTION') 
    //Use production DB
else 
    //Use local DB
    sequelize = new Sequelize(...);


getGlobbedModels()
    .then(importModels)
        .fail(function(err)
            console.error('importModels err ' + err);
        )
    .then(associateModels)
        .fail(function(err)
            console.error('associateModels err' + err);
        )
    .then(synchronize)
        .fail(function(err)
            console.error('synchronize err' + err);
        );

// assign the sequelize variables to the db object and returning the db. 
module.exports = _.extend(
    sequelize: sequelize,
    Sequelize: Sequelize
, db);

在我的 app.js 文件中,我需要以下代码,但模型在导出到 require 调用时未定义。我已经验证了上面的 db 对象,并且模型成功地被要求,但没有被导出到 require 调用中。

app.js

var models = require('./sequelize_init.js');
models.User.findAll().then(); // Throws undefined error

【问题讨论】:

【参考方案1】:

您的模型是在设置module.exports 很久之后异步导入、关联等的,因此当您在模块末尾合并db 时,它仍然是一个空对象。

对此的一种解决方案是导出一个初始化函数,该函数接受一个回调,一旦所有初始化步骤完成,该回调就会被调用。例如:

sequelize_init.js

// ...

module.exports = function(cb) 
  getGlobbedModels()
      .then(importModels)
          .fail(cb)
      .then(associateModels)
          .fail(cb)
      .then(synchronize)
          .fail(cb)
      .then(function() 
        cb(null, _.extend(
          sequelize: sequelize,
          Sequelize: Sequelize
        , db));
      );
;

app.js

var init = require('./sequelize_init.js');
init(function(err, models) 
  if (err) throw err;

  models.User.findAll().then();
);

【讨论】:

谢谢!这行得通。你会建议一种替代方法来替代基于承诺的方法或改进上述代码吗?我需要每个控制器中的初始化文件来访问模型 这是一个偏好问题。如果你想严格遵守 Promise,你可以导出一个 Promise 而不是一个 init 函数,它会使用 _.extend(...) 的值来解决。

以上是关于Node.js module.exports 不导出整个对象的主要内容,如果未能解决你的问题,请参考以下文章

Node.js中exports与module.exports的区别

在 Node.js 中声明多个 module.exports

Node.js module.exports和exports的区别

node.js exports module.exports

node.js 中 module.exports= 函数的含义

Node.js的学习入门(module.exports与exports)