在node.js/Mongoose项目中,我有一个包含对外部图像文件的引用的模式.
var PageSchema = new Schema({
title: String
, media: {
digest: String
, name: String
}
});
Run Code Online (Sandbox Code Playgroud)
这些文件具有存储在文件本身中的其他属性:url,width,height,exif字段等.在将模型发送到res.render()之前,需要填充这些字段.
对于某些领域,事情是同步的,虚拟只是完成工作:
PageSchema.virtual('media.url').get(function () {
return appPaths.fileUrl(this.media);
});
Run Code Online (Sandbox Code Playgroud)
但是,宽度/高度或exif字段需要异步调用.我想过使用中间件来填充它们,但这似乎不起作用:
PageSchema.post('init', function(next) {
var media = this.media;
var fileName = filedb.absoluteFilePath(media);
im.identify(fileName, function(err, features) {
if (err) {
media.width = 0;
media.height = 0;
} else {
media.width = features.width;
media.height = features.height;
}
next();
});
});
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?是否有解决此类问题的通用设计模式?(除了在数据库本身中复制这些信息外?)
这里真正的问题是,mongoose目前似乎有一个不稳定的post回调实现.虽然pre('init',function(next){ ... });按预期工作,post('init',function(next){ ... });但实际上并没有传递next函数.事实上,post init回调在调用时不会收到任何参数.
因此,我经常为查询回调编写一个包装器来制作一种DIY中间件:
var setAsyncVirtuals = function(callback){
return function(err, docs){
if(err) return callback(err);
var i = done = docs.length;
if(i > 0)
while(i--){
(function(i){
var filename = getFilename();
im.identify(filename, function(err, features) {
if (err) {
docs[i].media.width = 0;
docs[i].media.height = 0;
} else {
docs[i].media.width = features.width;
docs[i].media.height = features.height;
}
done--;
if(done <= 0) callback(null, docs);
});
})(i); // bind i to hold value for async call
}
else callback(null, docs);
}
}
Run Code Online (Sandbox Code Playgroud)
然后
Page.find({}, setAsyncVirtuals(function(err,docs){
res.send(docs); // these have media.width & media.height assigned
}));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1552 次 |
| 最近记录: |