抱歉,我无法想出一个直截了当的问题/标题,但这就是问题所在。我有以下结构:
var userProvider=function(login){
this.getUser=mongoose.find(login).exec();
}
userProvider.prototype.doStuffWithUserData=function(){
this.getUser.then(function(user){
...
});
}
userProvider.prototype.doOtherStuffWithUserData=function(){
this.getUser.then(function(user){
...
});
}
有没有更好的方法,这样我就不需要在每个原型函数中调用promise,尽管原型函数只在数据存在之前进行评估?
答案 0 :(得分:1)
以下是如何通过装饰来完成的。这很棘手,因为当您创建函数时,承诺不可用:
function whenReady(fnToRun){
return function runsWhenReady(){ // the decorated function
// keep track of arguments
var args = Array(arguments.length + 1); // inline slice is much faster
for(var i = 0; i < arguments[i]; i++) args[i+1] = arguments[i];
return this.getUser.then(function(user){
args[0] = user;
return fnToRun.call(this, args); // append user and call with args
}.bind(this)); // maintain context)
};
}
这可以让你这样做:
userProvider.prototype.doStuffWithUserData = whenReady(function(user){
// user is available here
});
myUserProviderInstance.doStuffWithData(); // inside the call user is available
userProvider.prototype.otherStuff = whenReady(function(user, x){
// user is available here
});
myUserProvider.otherStuff(15); // x will be 15 and user will be available, promise returned
这种方法可以推广到一个更通用的whenReady
,它需要&#34; waitFor&#34;论点。值得一提的是,如果您使用像Bluebird这样的库,它已经附带bind
和method
,这样您就可以更轻松地执行此操作。
答案 1 :(得分:1)
有没有更好的方法,只有当数据存在时才会评估原型函数?
我建议不要在构造函数中执行find
sideeffect,并在那里创建承诺,但是将mongoose.find(login).exec()
的结果传递给构造函数,如列于Is it bad practice to have a constructor function return a Promise?
我会选择不好的做法
为避免重复,您可以像这样创建原型方法:
function userProviderMethod(n, m) {
UserProvider.prototype[n] = function() {
var args = Array.prototype.slice.call(arguments),
that = this;
return this.getUser.then(function(user) {
args.unshift(user);
return m.apply(that, args);
});
};
}
function UserProvider(login){
this.getUser = mongoose.find(login).exec();
}
userProviderMethod("doStuffWithUserData", function(user /*, … */) {
// …
});
userProviderMethod("doOtherStuffWithUserData", function(user) {
// …
});
请注意,当.getUser
被拒绝时,这些“方法”都不会被执行。