How to store mongodb output in variable using nodejs in lambda function?

做~自己de王妃 提交于 2019-12-25 17:04:25

问题


In a lambda function, I have the following code:

var user;

exports.handler = function uploadToS3(event, context, callback) {
  var name = event["username"];
  MongoClient.connect(uri, { useNewUrlParser: true }, (error, client) => {
    if (error) return 1; // Checking the connection
    db = client.db(databasename);
    db.collection("user_profile").findOne({ username: name }, function(
      err,
      result
    ) {
      if (err) throw err;
      user = result._id;
      console.log(user); // 1st console.log
    });
  });
  console.log(user); //2nd console.log
};

In the above code, I have declared user as a global variable. In 1st console.log it will display the value but in 2nd console.log it will undefined. find the below output of lambda function.

Function Logs:
2019-08-23T15:23:34.610Z    83141f62-f840-4e52-9440-35f3be7b0dc8     
5d5eaa9f921ed00001ee1c3f
2019-08-23T15:23:34.192Z    83141f62-f840-4e52-9440-35f3be7b0dc8     
undefined

How can I get a value in the second case?


回答1:


The problem is not so much storing the mongodb output into a variable, as it is a synchronous vs asynchronous behavior. Javascript by design is synchronous, but has capability to handle asynchronous tasks. The method that performs the mongo query is asynchronous. Read: Javascript calls findOne(), this returns an 'pending' promise, then your script continues to call console.log(user) - which is still undefined. When the request from MongoDB comes back, javascript resolves the promise and executes any further actions and/or callbacks.

The second console.log comes back and is evaluated BEFORE the mongo client returns a response and assigns a new value to your variable. If you look at the timestamp of the responses, the undefined one comes back before the one with the value. It looks like you are using mongoose, which should return a promise and you can try putting that second call inside a .then, or a .done block. e.g:

var user;

exports.handler = function uploadToS3(event, context, callback) {
  var name = event["username"];
  MongoClient.connect(uri, { useNewUrlParser: true }, (error, client) => {
    if (error) return 1; // Checking the connection
    db = client.db(databasename);
    db.collection("user_profile").findOne({ username: name }, function(
      err,
      result
    ) {
      if (err) throw err;
      user = result._id;
      console.log(user); // 1st console.log
    })
    .done(function(){
      console.log(user); //2nd console.log
    });
  });  
};

If not using mongoose... make your own promise, or use a callback, or just try Mongoose (it rocks!) :)

*note that I put the .done after the findOne(), but I believe you could attach a .done() to the .connect() as well. (Don't quote me on that. You would have to test it, see when that promise resolves exactly)

Additionally, I would suggest storing this value outside of your lambda somehow. You might not get the same container bootstrapped for each lambda execution. You could have some issues with this down the line.

Check out:

  • AWS Lambda caching issues with Global Variables - https://medium.com/tensult/aws-lambda-function-issues-with-global-variables-eb5785d4b876
  • Improving Performance From Your Lambda Function From the Use of Global Variables - https://blog.ruanbekker.com/blog/2018/08/27/improving-performance-from-your-lambda-function-from-the-use-of-global-variables/
  • AWS Lambda best practices - https://docs.aws.amazon.com/lambda/latest/dg/best-practices.html


来源:https://stackoverflow.com/questions/57629210/how-to-store-mongodb-output-in-variable-using-nodejs-in-lambda-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!