我正在使用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)
有关解决方案或替代方法的任何见解都表示赞赏。
答案 0 :(得分:4)
您需要返回then
中创建的承诺。现在,您正在为connect
解析时注册两个回调,但从未注册configure
和findAll
承诺的任何回调。
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);
})
您应该看到所需的行为。