简体   繁体   English

NodeJS MongoDB:如何获取数据然后同步返回

[英]NodeJS MongoDB: How do I get data then returning synchronously

I'm a long time programmer (mostly Java) but new to NodeJS/Express.我是一名资深程序员(主要是 Java),但对 NodeJS/Express 还是个新手。 The biggest problems I'm having are with async operations.我遇到的最大问题是异步操作。 Some of my code is working fine, like when I can do a async database operation then just pass the results to res.render().我的一些代码工作正常,比如当我可以执行异步数据库操作然后将结果传递给 res.render() 时。

In this particular case, I'm in a route handler, and I need to make a call to a function I wrote in the controller to get something from the database, then do something else and then do the render in the route handler.在这种特殊情况下,我在路由处理程序中,我需要调用我在 controller 中编写的 function 以从数据库中获取某些内容,然后执行其他操作,然后在路由处理程序中进行渲染。 In other words, I need to run the function then return control with results back to the router.换句话说,我需要运行 function 然后将控制权和结果返回给路由器。 Everything I have tried is not even compiling, just hangs, or I immediately get back two undefined values.我尝试过的一切甚至都没有编译,只是挂起,或者我立即得到两个未定义的值。 My current pattern is similar to the accepted solution in mongoDB with nodejs return data but I'm not getting my data back.我当前的模式类似于 mongoDB 中接受的解决方案, 其中包含 nodejs 返回数据,但我没有取回数据。

I've REALLY tried to understand this async/await stuff but it's just not working as I would expect.我真的试图理解这种异步/等待的东西,但它并没有像我预期的那样工作。

The caller in the route handler looks like this:路由处理程序中的调用者如下所示:

app.get('/', async (req, res) => {
    debug("app calling list:");
    const { listInsightErrors, listInsightResults } = await listInsightPeriods();
    debug("app results: %O %O", listInsightErrors, listInsightResults);
    res.render('index', {
        appConfig,
        listInsightErrors,
        listInsightResults
    });
});

The function I'm calling looks like this:我拨打的 function 如下所示:

async function listInsightPeriods() {
        var sortKey = { clientId: 1, insightName: 1 };
        var listInsightErrors = {};
        var listInsightResults = {};
        client = await MongoClient.connect(appConfig.mongoUrl);
        const db = client.db(appConfig.mongoDatabase);
        const collection = db.collection('teamInsights');
        let garbage = await collection.find({})
            .project({ 'clientName': 1, 'insightName': 1 })
            .sort(sortKey)
            .toArray((errors, results) => {
                if (errors) {
                    debug('listInsightPeriods find error: %O', errors);
                } else {
                    debug('listInsightPeriods got results: %O', results);
                }
                listInsightErrors = errors;
                listInsightResults = results;
                debug("closed, returning %O %O", listInsightErrors, listInsightResults);
                return { listInsightErrors, listInsightResults };
                debug("Passed inside return");
            });
        debug("Outside of db call");
        return { listInsightErrors, listInsightResults };
    }

What happens is listInsightPeriods gets the data just fine, but the route handler doesn't get it, and I see the debugging output from the route handler before I see the debugging output from listInsightPeriods.发生的事情是 listInsightPeriods 可以很好地获取数据,但路由处理程序没有获取数据,在我看到来自 listInsightPeriods 的调试 output 之前,我从路由处理程序中看到了调试 output。 So I don't feel the route handler is waiting for the data to return.所以我不觉得路由处理程序正在等待数据返回。

Any help you can offer would be great.你能提供的任何帮助都会很棒。 I've read so many pages on this and I still can't get it.我已经阅读了很多关于此的页面,但我仍然无法理解。 Thanks.谢谢。

The toArray function also returns a Promise, so if you're using async/await you can try this approach in your listInsightPeriods function toArray function 还返回 Promise,因此如果您使用异步/等待,您可以在 listInsightPeriods function 中尝试这种方法

async function listInsightPeriods() {
  const response = {
    listInsightErrors: null,
    listInsightResults: null
  }
  try{
    client = await MongoClient.connect(appConfig.mongoUrl);
    const db = client.db(appConfig.mongoDatabase);
    const collection = db.collection('teamInsights');
    const results  = await collection.find({})
        .project({ 'clientName': 1, 'insightName': 1 })
        .sort({ clientId: 1, insightName: 1 })
        .toArray();
    debug("listInsightPeriods got results: %O", results);
    response.listInsightResults = results;
  }catch(e){
    debug("listInsightPeriods find error: %O", e);
    response.listInsightErrors = e;
  }

  return response;
}

you can use 'callback' concept.您可以使用“回调”概念。

callback is amazing.回调是惊人的。

this code is for you and i tested.这段代码是为你和我测试过的。 it's work ok.它工作正常。

const express = require("express")
const mongo = require("mongodb")
const app = express()

const appConfig = {
  mongoUrl: "mongodb://127.0.0.1:27017/local",
  mongoDatabase: "local"
}

let client;
let dataBase;
mongo.connect(appConfig.mongoUrl, {}, (err, client) => {
  if (err) {
    this.client = null;
    this.dataBase = null;
    return;
  }
  client = client;
  dataBase = client.db(appConfig.mongoDatabase);
  debug("connected to database");
});

app.listen(4000, () => {
  debug("Server is listening on port: 4000");
})

app.get("/", (req, res) => {
  debug("app calling list:");
  listInsightPeriods(function (error, result) {
    debug("app results: %O %O", error, result);
    res.json({
      error,
      result
    })
    // res.render("index", {
    //   appConfig,
    //   error,
    //   result
    // });
  });
});

function listInsightPeriods(callback) {
  var sortKey = { clientId: 1, insightName: 1 };
  dataBase.collection("teamInsights")
    .find({})
    .project({ clientName: 1, insightName: 1 })
    .sort(sortKey)
    .toArray((errors, results) => {
      if (errors) {
        debug("listInsightPeriods find error: %O", errors);
      } else {
        debug("listInsightPeriods got results: %O", results);
      }
      debug("closed, returning %O %O", errors, results);
      return callback(errors, results);
    });
}

function debug(...params) {
  console.log(params)
  // params.forEach(param => {
  //   console.log(param)
  // });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM