首页 > 解决方案 > 如何在 lambda 函数中使用 nodejs 将 mongodb 输出存储在变量中?

问题描述

在 lambda 函数中,我有以下代码:

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
};

在上面的代码中,我将 user 声明为全局变量。在第一个 console.log 中它将显示该值,但在第二个 console.log 中它将未定义。找到以下 lambda 函数的输出。

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

在第二种情况下如何获得价值?

标签: node.jsaws-lambda

解决方案


问题不在于将 mongodb 输出存储到变量中,而在于它是同步与异步行为。Javascript 在设计上是同步的,但具有处理异步任务的能力。执行 mongo 查询的方法是异步的。阅读:Javascript 调用 findOne(),这会返回一个“待定”的承诺,然后你的脚本继续调用 console.log(user) - 这仍然是未定义的。当来自 MongoDB 的请求返回时,javascript 解析承诺并执行任何进一步的操作和/或回调。

第二个 console.log 在 mongo 客户端返回响应并为您的变量分配一个新值之前返回并进行评估。如果您查看响应的时间戳,未定义的会在具有值的时间戳之前返回。看起来您正在使用 mongoose,它应该返回一个 Promise,您可以尝试将第二个调用放在 .then 或 .done 块中。例如:

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
    });
  });  
};

如果不使用猫鼬......做出你自己的承诺,或者使用回调,或者只是尝试猫鼬(它摇滚!):)

*请注意,我将 .done 放在 findOne() 之后,但我相信您也可以将 .done() 附加到 .connect()。(不要引用我的话。您必须对其进行测试,看看该承诺何时准确解决)

此外,我建议以某种方式将此值存储在您的 lambda 之外。您可能不会为每个 lambda 执行引导相同的容器。你可能会遇到一些问题。

查看:


推荐阅读