使用带有'require'的promise来动态加载模块

时间:2016-09-09 16:42:28

标签: node.js mongoose promise

我正在使用mongoose并尝试使用'require'动态加载架构/模型,但我得到了不寻常的行为。更具体地说,'require'在promise链完成后执行,这不是我预期的。相反,我本来期望同步(从我理解的)完成'require',然后按顺序调用promise.resolve来维护promise链。

(注意:我认为mongoose不参与此问题,但在此示例中用于说明问题)

我的代码(简化以说明问题)如下所示:

var Promise = require('bluebird');
var mongoose = require('mongoose');

function connect(){
  console.log('Connecting');
  return new Promise(function(resolve,reject){
    mongoose.connect('mongodb://localhost/mongodb');
    mongoose.connection.on('connected', function () {
        resolve();
    });
  });
}

function configure(fileName){
  console.log('Configuring filename: %s', fileName);
  return new Promise(function(resolve,reject){
    console.log('Requiring filename: %s', fileName);
    require(filename);
    console.log('Required filename: %s', fileName);
    resolve();
  });
}

function findAll(modelName){
  console.log('Finding');
  mongoose.model(modelName).find(function(err, data) {
    console.log('Model: %s, found items: %s', modelName, data);
  });
}

var modelName = 'users';
var modelFile = './' + modelName;
connect()
  .then(function(){
    configure(modelFile);
  })
  .then(function(){
    findAll(modelName);
  })
  .catch(function(err){
    console.log('Mainline promise error: %s', err.stack);
    process.exit(0);
  });

包含架构和模型创建的模块('users.js')(在'require'中加载)如下所示。请注意,因为'require'没有完成,我假设没有加载这个模块,但为了完整性我已经包含它:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

console.log('users schema starting');
var schema = new Schema({
  firstname: String,
  lastname: String,
  middlename: String
});

var users = mongoose.model('users', schema);
console.log('users schema defined');

module.exports = users;

下面的控制台消息说明'require'似乎不按顺序执行(即'require'启动,后续的promise被解析,但'require'不能同步完成)。因此,当“发现”发生时,模式/模型不可用:

Connecting
Configuring filename: ./users
Requiring filename: ./users
Finding
Mainline promise error: MissingSchemaError: Schema hasn't been registered for model "users".
Use mongoose.model(name, schema)
    at Mongoose.model ({user-dir}node_modules/mongoose/lib/index.js:349:13)
    at findAll ({user-dir}main.js:28:14)
    at {user-dir}main.js:40:9
    at tryCatcher ({user-dir}node_modules/bluebird/js/main/util.js:26:23)
    at Promise._settlePromiseFromHandler ({user-dir}node_modules/bluebird/js/main/promise.js:507:31)
    at Promise._settlePromiseAt ({user-dir}node_modules/bluebird/js/main/promise.js:581:18)
    at Promise._settlePromises ({user-dir}node_modules/bluebird/js/main/promise.js:697:14)
    at Async._drainQueue ({user-dir}node_modules/bluebird/js/main/async.js:123:16)
    at Async._drainQueues ({user-dir}node_modules/bluebird/js/main/async.js:133:10)
    at Immediate.Async.drainQueues [as _onImmediate] ({user-dir}node_modules/bluebird/js/main/async.js:15:14)
    at processImmediate [as _immediateCallback] (timers.js:383:17)    

有关解决方案或替代方法的任何见解都表示赞赏。

1 个答案:

答案 0 :(得分:4)

您需要返回then中创建的承诺。现在,您正在为connect解析时注册两个回调,但从未注册configurefindAll承诺的任何回调。

connect()
.then(function(){ // called when connect resolves
  configure(modelFile); // creates a new promise
})
.then(function(){ // called when connect resolves and the previous function returns
  findAll(modelName);
})

如果您将其更改为:

connect()
.then(function(){
  return configure(modelFile);
})
.then(function(){ // called when the promise from the previous function resolves
  return findAll(modelName);
})

您应该看到所需的行为。