0

It's a silly question perhaps, but I spent quite sometime trying to resolve but not able to get the data.

In the below function checkMailCount, I have an object called test with a function in it to assign the value to mails. The value assigned from res.on('end') to this test.mails via mailCount is not retained/persisting.

'use strict';

const https = require('https');

exports.handler = (event, context, callback) => {

    let session = event.session;
    let request = event.request;

    if (request.type === "something") {
        if (request.name === "blah blah") {

            let emailCount = checkMailCount(session, callback);

            context.succeed(callback(null, emailCount));
        }
    }

    function checkMailCount(session, callback) {

        let url = 'https://www.googleapis.com/gmail/v1/users/me/messages? 
        access_token = $ {
            session.user.accesstoken
        } & q = "is:unread"
        ';

        let test = {
            mails: "",
            mailCount: function(val) {
                this.mails = val;
            }
        };

        let data = "";

        https.get(url, function(res) {

            res.on('data', function(chunk) {
                data += chunk;
                //console.log(data);
            });

            res.on('end', function() {
                let result = JSON.parse(data);
                //result2+= result.replace('/\//g','');
                test.mailCount(result["resultSizeEstimate"]);

                // result["resultSizeEstimate"] inaccessible outside
            });

        });


        return test.mails; // This is returning undefined
    }

    //context.fail();
}

Below is the response JSON from gmail API

{
 "messages": [
  {
   "id": "165f1627a53f70c6",
   "threadId": "165f000031cee15b"
  },
  {
   "id": "165f00d9e2e07737",
   "threadId": "165f00d9e2e07237"
  }
 ],
 "nextPageToken": "10349401829330188334",
 "resultSizeEstimate": 2
}

I need to return the value of result["resultSizeEstimate"] from the function checkMailCount. The value of result, result["resultSizeEstimate"] is available inside res.on('end', f(){It is available here}) but not outside.

I tried this in VS code not as lambda, I was able to do it by other means. Its sort of hard to unit test lambda functions. Is there a way, I can send the email count to context.succeed(callback(null, emailCount)) ?

dee
  • 2,244
  • 3
  • 13
  • 33

1 Answers1

0

It seems like there's a fundamental issue with callbacks in this code. It is not possible for checkMailCount to behave like you want it to in its current form. checkMailCount is asynchronous. JavaScript has a few different ways to deal with asynchronous code. The oldest is what you're doing here, callbacks. Next is promises and finally async/await. This code is probably easier to write if you switch to async/await. That said, if you want to keep using the callback pattern you're gonna have to ya know, use them.

Instead of passing lambda's callback to checkMailCount you should pass your own.

checkMailCount(session, function(err, result) {
    // result === result.resultSizeEstimate
    // Call your lambda callback from within this function
});


res.on('end', function() {
    let result = JSON.parse(data);
    test.mailCount(result["resultSizeEstimate"]);
    callback(null, result.resultSizeEstimate)    
});
Andy Gaskell
  • 31,495
  • 6
  • 74
  • 83