【问题标题】:How override `this` in the mongoose.Schema.prevalidate middleware?如何在 mongoose.Schema.prevalidate 中间件中覆盖 `this`?
【发布时间】:2014-03-13 02:09:42
【问题描述】:

我不明白为什么我的模型实例没有被覆盖

schema.pre('validate', function(callback: any, done: any){
    if(!this.status){
        var Type = __Dao.getModel('type');
        Type.findOne({name: 'processing', 'category.name': 'languageStatus'}, function(err, role){
            if(err){
                callback(err);
            }else{
                console.log('this: '+JSON.stringify(this))
                this.status = role;
                callback();
            }
        });
    }
    done();
});

控制台

this: {"domain":null,"_events":{},"_maxListeners":10,"emitted":{"complete":[{"code":"a","name":"processing","_id":"52fd475c699127802d298665"}]},"ended":false}

// 其他console.log {消息:'验证失败', 名称:'验证错误', 错误: { 状态: { 消息:'路径 status 是必需的。', 名称:'ValidatorError', 路径:'状态', 类型:'必需', 值:未定义 } } }

我检查了,我的role 不是空的。 我认为我的错误在this.status = role; 上,this 已定义,但看起来我没有以好的方式覆盖它。

有什么建议吗?

【问题讨论】:

  • 设置状态后不需要也保存吗?第二个日志行什么时候发生?
  • 当我尝试在我的app.js 中保存一个假模型时,会出现第二行。我应该保存它吗?如何?这不是模型,不是吗?只需致电this.save()?我以为我只需要更改对象,它就会自动保存。我真的不知道。

标签: node.js mongodb mongoose middleware


【解决方案1】:

尝试保存模型并从那里记录任何错误。所以在这行之后:this.status = role; 这样做:

this.save(function(err, info) {
    if(err) {
        console.log('Error saving the model:', err);
        return;
    }
    console.log('Saved: ', info);
});

它可能会给你更多关于失败的信息。

【讨论】:

  • 对我来说这看起来像是一个 hack,我的意思是,我将调用将调用 .validate 的 .save(),在内部我应该调用也将调用 .validate 的 .save,将通过验证,然后自动调用 .save ?很奇怪,不是吗?
  • 我试过了,this.save回调没有被触发,我的console.log根本没有被调用。
  • 但是错误日志中还有其他内容吗?显然你的验证失败了。你能显示整个验证码吗?
  • jwags 解决方案适用于我,使用并行。它不能连续工作,我不知道为什么。
【解决方案2】:

正如您所提到的,this.status 似乎不是正确的对象。看起来您可能错误地使用了并行中间件。 Middleware 可以定义为串行Schema.pre('save', function (done) {... 或并行Schema.pre('save', true, function (next, done) {...。请注意,第二个 arg 是一个布尔值,表示它应该并行运行。

对于并行尝试以下操作:

schema.pre('validate', true, function(next, done){
    var self = this; // save a reference to status
    next();  // start working on any other middleware in parallel with this one

    if(!self.status){
        var Type = __Dao.getModel('type');

        return Type.findOne({name: 'processing', 'category.name': 'languageStatus'}, function(err, role){
            if(err){
                done(err);
            }else{
                console.log('status: '+JSON.stringify(status))
                self.status = role;
                done();  // signify this middleware's work is done
            }
        });
    }
    done();
});

如果这不起作用,您可以尝试使用串行中间件,以确保您在其他中间件中没有冲突。

更新:只有当您拥有多个中间件时,并行和串行之间的差异才有意义。 Parallel 使您能够同时运行所有中间件,然后在所有完成后继续进行实际验证。 Serial 会做第一个中间件,在前一个完成后等待开始下一个,然后在所有完成后验证。

例如,您的客户端服务运行在一台必须通过网络向数据库发送请求的机器上。时间可能不准确,但为了讨论,我们假设这些请求大约需要 100 毫秒。使用串行中间件:

Schema.pre('validate', function (done) {
    Type.findOne({ name: 'steve' }, function (err, doc) { // send request across network
        // ~100ms later we get steve
        // pre validate steve ...
        done(); // Start the next piece of middleware after this is done
    });
});

Schema.pre('validate', function (done) {
    Type.findOne({ name: 'Jim' }, function (err, doc) { // send request across network
        // ~100ms later we get Jim
        // pre validate Jim ...
        done(); // Start the next piece of middleware after this is done
    });
});

总时间 == ~ 200+ms

如果您并行运行它们,则对数据库的请求几乎可以同时进行。

Schema.pre('validate', true, function (next, done) {
    next(); // start the next piece of middleware before sending request
    Type.findOne({ ... }, function (err, doc) { // send request across network
        // ~100ms later we get the doc
        // do stuff ...
        done();
    });
});

Schema.pre('validate', true, function (next, done) {
    next(); // start the next piece of middleware before sending request
    Type.findOne({ ... }, function (err, doc) { // send request across network
        // ~100ms later we get the doc
        // do stuff ...
        done();
    });
});

总时间 ~ 100+ms

【讨论】:

  • 我阅读了文档,但老实说我有点迷失了这种parallel 模式,我并没有真正理解整个事情,两者和提供的参数有什么区别?
  • return 声明在这里重要吗? findOne 是同步的。
  • 好的,所以我做了更改,但它仍然不起作用。 status 之前是未定义的,但在status = role; 之后他被定义了。但我仍然收到验证错误。
  • 返回很重要,因为 findOne 是异步的。我刚刚意识到我的代码有错误,我会更新
  • 我想知道this 以及您的代码如何更新当前实例中的任何内容^^ 更好,我会尝试。
猜你喜欢
  • 1970-01-01
  • 2016-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-07
  • 1970-01-01
  • 2019-10-16
相关资源
最近更新 更多