具有原型函数的用户提供程序对象中的Mongoose承诺

时间:2014-10-02 20:46:21

标签: javascript node.js mongoose promise

抱歉,我无法想出一个直截了当的问题/标题,但这就是问题所在。我有以下结构:

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,尽管原型函数只在数据存在之前进行评估?

2 个答案:

答案 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这样的库,它已经附带bindmethod,这样您就可以更轻松地执行此操作。

答案 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被拒绝时,这些“方法”都不会被执行。