节点js:Bluebird Promisify在Mongoose中间件中

时间:2015-09-26 05:53:00

标签: node.js express mongoose bluebird

我的用户模型看起来像这样:

var Promise = require("bluebird")
var mongoose = require("mongoose");
var mongooseAlias = require('mongoose-aliasfield');
var bcrypt = Promise.promisifyAll(require('bcrypt-nodejs'));

var Schema = mongoose.Schema;

var userSchema = new Schema({
    u:  { type: String, required: true, trim: true, index: { unique: true }, 'alias': 'userId' },
    fb: { type: String, required: true, 'alias': 'fbAccessToken' },
    ap: { type: String, required: true, 'alias': 'apiAccessToken' },
    f:  { type: String, required: true, 'alias': 'firstName' },
    l:  { type: String, required: true, 'alias': 'lastName' },
    e:  { type: String, required: true, 'alias': 'email' }
});

// Execute before each user.save() call
userSchema.pre('save', function(callback) {
    var user = this;

    // return if token hasn't changed
    if (!user.isModified('fb') && !user.isModified('ap'))
        return callback();

    // token changed so we need to hash it
    bcrypt.genSalt(5, function(err, salt) {
        if (err) return callback(err);
        bcrypt.hash(user.fb, salt, null, function(err, hash) {
            if (err) return callback(err);
            user.fb = hash;
            bcrypt.genSalt(5, function(err, salt) {
                if (err) return callback(err);
                bcrypt.hash(user.ap, salt, null, function(err, hash) {
                    if (err) return callback(err);
                    user.ap = hash;
                    callback();
                });
            });
        });
    });
});

userSchema.plugin(mongooseAlias);

module.exports = mongoose.model('User', userSchema);

我正在尝试学习Bluebird,所以我清理了像这样的bcrypt代码:

userSchema.pre('save', function(callback) {
    var user = this;
    // return if token hasn't changed
    if (!user.isModified('fb') && !user.isModified('ap'))
        return callback();

    var p1 = bcrypt.genSaltAsync(5).then(function (salt) {
        return bcrypt.hash(user.fb, salt, null);
    }).then(function (hash) {
        user.fb = hash;
    });
    var p2 = bcrypt.genSaltAsync(5).then(function (salt) {
        return bcrypt.hash(user.ap, salt, null);
    }).then(function (hash) {
        user.ap = hash;
    });

    Promise.all(p1, p2).then(function () {
        callback();
    }).catch(function (err) {
        callback(err);
    });
});

我可以进一步“宣传”吗?或者更确切地说,我在这里错过了一些会让它更优雅的东西吗?我是否需要以某种方式宣传userSchema.pre电话?

干杯

1 个答案:

答案 0 :(得分:0)

我认为你的解决方案是正确的。我更喜欢这样做(但我并不是说这更好):

bcrypt.genSaltAsync(5)
.then(function (salt) {
    return bcrypt.hash(user.fb, salt, null);
})
.then(function (hash) {
    user.fb = hash;
})
.then(function (){
    return bcrypt.genSaltAsync(5);
})
.then(function (salt) {
    return bcrypt.hash(user.ap, salt, null);
})
.then(function (hash) {
    user.ap = hash;
})
.then(function () {
    callback();
})
.catch(function (err) {
   callback(err);
});

我喜欢我的解决方案,因为一切都在一个流程中,乍一看你知道发生了什么。在我的解决方案中,第二个盐函数首先解析。在您的解决方案中,每个解决方案并行解析(我不检查每个解决方案的性能)