Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose schema virual and async await

I'm trying to get a value from mongoose and add it to the schema document by using virtual method and virtual field as like follows,

const sourceSchema = require('../source/schema.js').schema;
var Source = mongoose.model('Source', sourceSchema);

const schema = new Schema({
  sourceId: {
    type: Schema.Types.ObjectId,
    required: true
  },
  description: {
    type: String,
    required: true
  },
  resources: {
    type: Object
  },
  createdDate: {
    type: Date
    }
  }
}, 
{
  versionKey: false,
  virtuals: true
});

schema.virtual('displayName').get(function () {
  return this.getDisplayName();
});

schema.method('getDisplayName', async function () {
  var source = await Source.findById(this.id);
  if(source) {
    var displaySource = JSON.parse(source['data']);    
    console.log(displaySource['displayName']);
    return displaySource['displayName'];
  }
});

But it's always coming as empty whereas it's printing the value in console, it never waits for the execution to complete. I'm not sure why it's not waiting for the execution while I'm using await.

Any help on this would be greatly helpful and much appreciated.

like image 672
Stranger Avatar asked Oct 16 '25 02:10

Stranger


2 Answers

Getters and Setters cannot be async, that's just the nature of JS.

You never called callback

schema.method('getDisplayName', async function (cb) { // <-- added callback
  var source = await Source.findById(this.id);
  if(source) {
    var displaySource = JSON.parse(source['data']);    
    console.log(displaySource['displayName']);
    cb(displaySource['displayName'])                  // <-- called callback
  } else cb(null)
});

Then somewhere in code

Schema.findOne(function (err, schema) {
  schema.getDisplayName(function (displayName) {
   // got it here
  })
})

Note that schema.virtual('displayName') is removed

like image 77
Medet Tleukabiluly Avatar answered Oct 18 '25 14:10

Medet Tleukabiluly


I defined displayName as:

schema.virtual("displayName").get(async function () {
  const souce = await Source.findById(this.id);
  if (source) {
    return source.displayName;
  }
  return undefined;
});

The property must have await before referencing it, like this:

  const name = await sourceDoc.displayName;

as the property is an async function elsewhere. If somebody can teach me how to call an async function without await I'd be very happy.

like image 26
Victor Ian Avatar answered Oct 18 '25 15:10

Victor Ian



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!