MongoDB Functions doesn't return as expected

I try to get result from another function and use that return values. But context.functions.execute only works when I return the values immediately. It means that if I use this way, it works perfectly:

exports = () => {
  var res;
  res = context.functions.execute("listTodayBookings");
  return res

But not this way

exports = () => {
  var res, compare;
  var today = new Date();
  var h = today.getHours() + 7; //GMT +7
  var m = today.getMinutes();
  var time = h + ":" + m;
  res = context.functions.execute("listTodayBookings");
  for (let k in res) {
    console.log(k, res[k])
  }

res will be undefined and print nothing. Any helps are appreciated.

Hi @Tuan_Nguyen1 welcome to the community!

What is listTodayBookings returning? If it’s an asynchronous function then it could be that res is an unresolved promise and you need to use the await or .then syntax.

Thank you for your response. I also tried async and await but it didn’t work though. listTodayBookings returns a dictionary. If I call and return it, it worked well. But I need to do some works before returning.

Are you able to share listTodayBookings (or a mocked-up version of it?)

listTodayBookings function:

exports = function(){
  const mongodb = context.services.get("mongodb-atlas");
  const db = mongodb.db("test");
  const bookings = db.collection('bookings');
  var d = new Date();
  var i = d.getDay();
  var days = ['MON','TUE','WED','THU','FRI','SAT','SUN'];
  var query = {};
  var res = {};
  var time = days[i];
  query[days[i]] = {'$exists': true};
  var todayBookings = bookings.find(query, {"_id": 0});
  todayBookings.toArray().then(data => {
    data.forEach(doc => {
      res[doc['Full Name']] = doc[time];
    });
  });
  return res;
};

checkCancel function:

exports = () => {
  var res, compare;
  var arr = [];
  res = context.functions.execute("listTodayBookings");
  var today = new Date();
  var h = today.getHours() + 7; //GMT +7
  var m = today.getMinutes();
  var time = h + ":" + m;
  // Object.entries(res).forEach(([k,v]) => console.log(k,v))
  // console.log(time);
  // return Object.entries(res)
  return Object.keys(res).length
  // if (res) {
  //   for (let k in res){
  //     console.log(k, res[k])
  //   }
  // }
};

I use those functions to list Customers who have bookings the current day and check if they’re late or not. Please take a look and if you have any solutions for this, I’ll appreciate it very much.

@Tuan_Nguyen1 I added some instrumentation to a cut-down version of listTodayBookings to show the order that instructions are executed:

exports = function(){
  const mongodb = context.services.get("mongodb-atlas");
  const db = mongodb.db("RChat");
  const bookings = db.collection('ChatMessage');
  var res = {};
  var todayBookings = bookings.find({}, {"_id": 0});
  console.log(`About to fetch data`);
  todayBookings.toArray().then(data => {
    console.log(`About to process docs`);
    data.forEach(doc => {
      console.log(`Processing doc`);
      res[doc['Full Name']] = "Fred";
    });
  });
  console.log(`Returning`);
  return res;
}; 

These are the results:

About to fetch data
Returning
About to process docs
Processing doc
Processing doc

As you can see, the results are returned before the .then block is executed.

Moving the return to within the .next block means that things get executed in the correct order:

exports = function(){
      const mongodb = context.services.get("mongodb-atlas");
      const db = mongodb.db("RChat");
      const bookings = db.collection('ChatMessage');
      var res = {};
      var todayBookings = bookings.find({}, {"_id": 0});
      console.log(`About to fetch data`);
      todayBookings.toArray().then(data => {
        console.log(`About to process docs`);
        data.forEach(doc => {
          console.log(`Processing doc`);
          res[doc['Full Name']] = "Fred";
        });
        console.log(`Returning`);
        return res;
      });
    };

Results:

About to fetch data
About to process docs
Processing doc
Processing doc

I use the return as you recommended but it seems not working though. The console.log inside forEach worked. But the return has no luck. ("$undefined": true).
The console.log inside forEach print:
‘Nguyen Tuan’
‘Nguyen A’
‘Nguyen B’

exports = function(){
	  const mongodb = context.services.get("mongodb-atlas");
	  const db = mongodb.db("test");
	  const bookings = db.collection('bookings');
	  var d = new Date();
	  var i = d.getDay();
	  var days = ['MON','TUE','WED','THU','FRI','SAT','SUN'];
	  var query = {};
	  var res = {};
	  var time = days[i];
	  query[days[i]] = {'$exists': true};
	  var todayBookings = bookings.find(query, {"_id": 0});
	  todayBookings.toArray().then(data => {
		data.forEach(doc => {
		  console.log(doc['Full Name'])
		  res[doc['Full Name']] = doc[time];
		});
		return res;
	  });
	};

Hello Andrew, I figured out how to handle this case

listTodayBookings function:

exports = () => {
  const mongodb = context.services.get("mongodb-atlas");
  const db = mongodb.db("test");
  const bookings = db.collection('bookings');
  var d = new Date();
  var i = d.getDay();
  var days = ['SUN', 'MON','TUE','WED','THU','FRI','SAT'];
  var query = {};
  var res = {};
  var time = days[i];
  query[days[i]] = {'$exists': true};
  var todayBookings = bookings.find(query, {"_id": 0});
  return todayBookings.toArray().then(data => {
	data.forEach(doc => {
	  res[doc['Full Name']] = doc[time];
	});
	return res;
  });
}

the other one:

exports = async () => {
  var res, compare;
  var today = new Date();
  var h = today.getHours() + 7; //GMT +7
  var m = today.getMinutes();
  var time = h + ":" + m;
  res = await context.functions.execute("listTodayBookings");
  for (let k in res) {
	console.log(k, res[k])
  }
}
2 Likes

Ah yes, not returning the results from the handled promise – that’s caught out more people than I can count!

Glad to hear that you’ve got it working.

2 Likes

Thank you so much for blazingly fast responses.

1 Like

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.