2

In this case I have two models: Protocol and Comment. Each model has a middleware('pre' or 'remove') that calls the other model. Calling the Comment middleware in Comment.js stops at Protocol.findById() because Protocol is an object instead of a model function. Here is the console.log(Protocol) in Comment.js

Protocol : [object Object] Type : object

When const Comment = require('../models/comment') is removed in Protocol.js, then the Comment.js middlware works, and Protocol inside it is seen by the console as follow:

Protocol : function model(doc, fields, skipId) {
  model.hooks.execPreSync('createModel', doc);
  if (!(this instanceof model)) {
    return new model(doc, fields, skipId);
  }
  Model.call(this, doc, fields, skipId);
} Type : function

I don't understant this behaviour. Moreover, in the other way around, the Protocol.js middleware works fine eventhough Comment.js has const Protocol = require('../models/protocol')

I found out a trick in another topic, which is to replace inside the middleware Protocol.findById() by mongoose.model('Protocol').findById(), but this doesn't explain the issue.

Scripts are presented below. If you need more information please let me know and I'll provide it. Thanks

Protocol.js model & middleware

// Dependencies
const mongoose = require('mongoose')

//Models
//<!---- If Comment is not required here then the Comment Middleware works ---->!
const Comment = require('../models/comment')

//Schema
const protocolSchema = mongoose.Schema({
    _id : mongoose.Schema.Types.ObjectId,
    title:  {
        type : String,
        required: true
    },
    comments : [{
        type: mongoose.Schema.Types.ObjectId,
        ref : 'Comment',       
    }]
})

//Middleware Hook Call
protocolSchema.pre('remove', async function() { 
    console.log('Starts Protocol.schema.pre(\'remove\')')

    var toBeDeletedProtocol = this

    await removeComments()

    function removeComments(){
        return new Promise ((resolve, reject) => {
            console.log('Starts removeComments()')
            var deletedComments = []

            Comment.find({protocol : toBeDeletedProtocol._id})
            .exec()
            .then( comments => {
                console.log('comments found: ' + comments)
                return resolve()
            })
            .catch(err => {
                console.log('Removing comment(s) related to the deleted protocol failed in protocol remove Hook')
                return reject(err)
            })
        })
    }
}) 

//Model Export
module.exports = mongoose.model('Protocol', protocolSchema)

Comment.js model & middleware

//Dependencies
const mongoose = require('mongoose')

//Models
const Protocol = require('../models/protocol')

//Schema
const commentSchema =  mongoose.Schema(
    {
        _id : mongoose.Schema.Types.ObjectId,
        content: {
            type: String, 
            required : true
        },
        protocol : {
            type: mongoose.Schema.Types.ObjectId,
            ref : 'Protocol',
            required : true,
        }
    }
)

//Middleware Hook Call
commentSchema.pre('save', async function() {
    console.log('Starts Comment.schema.pre(\'save\')')

    var toBeSavedComment = this

    await updateProtocol()

    function updateProtocol(){
        return new Promise ((resolve, reject) => {
            console.log('Starts updateProtocol()')

            console.log('toBeSavedComment : '+ toBeSavedComment) 
            console.log('Protocol : '+ Protocol, 'Type : ' + typeof Protocol)        
            //<!----- the ERROR occurs here -----!>
            Protocol.findById(toBeSavedComment.protocol)
            //<!----- Protocol is seen an object instead of a model function -----!>
            .exec()
            .then( protocol => {
                console.log('protocol found : ' + protocol)
                return resolve()
            })
            .catch(err => {
                console.log('Error in updateProtocol() in Comment.schema pre \'save\'') 
                console.log(err)
                return reject(err)
            })

        })
    } 

})    
//Export
module.exports = mongoose.model('Comment', commentSchema

)

Package.json

{
  "name": "debug",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node server.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "body-parser": "^1.18.3",
    "express": "^4.16.4",
    "mongoose": "^5.3.2",
    "nodemon": "^1.18.4"
  }
}

1 Answers1

0

It has been a while, and I haven't face the same issue so far, so I still don't have a clear solution. But I now see a mistake that could possibly lead to this unexplained behavior. I was concatenating variables or objects in console.log, eg :

console.log('toBeSavedComment : '+ toBeSavedComment) 
console.log('Protocol : '+ Protocol, 'Type : ' + typeof Protocol)

Instead do use comma "," :

console.log('toBeSavedComment : ', toBeSavedComment) 
console.log('Protocol : ', Protocol, 'Type : ' , typeof Protocol)

Object concatenation in console.log, for instance, in Amazone Web Service: Elastic Beanstalk prevent the API compilation.

This is not real answer, but I hope this might help!