NodeJS MongoDB: как получить данные, которые затем возвращаются синхронно - PullRequest
0 голосов
/ 05 мая 2020

Я давно программист (в основном Java), но новичок в NodeJS / Express. Самые большие проблемы у меня возникают с операциями asyn c. Часть моего кода работает нормально, например, когда я могу выполнить операцию с базой данных asyn c, тогда просто передайте результаты в res.render ().

В этом конкретном случае я нахожусь в обработчике маршрута , и мне нужно вызвать функцию, которую я написал в контроллере, чтобы получить что-то из базы данных, затем сделать что-то еще и затем выполнить рендеринг в обработчике маршрута. Другими словами, мне нужно запустить функцию, а затем вернуть управление с результатами обратно маршрутизатору. Все, что я пробовал, даже не компилируется, просто зависает, или я сразу получаю два неопределенных значения. Мой текущий шаблон аналогичен принятому решению в mongoDB с nodejs возвращаемыми данными , но я не получаю свои данные обратно.

Я ДЕЙСТВИТЕЛЬНО пытался понять этот async / await все, но он просто не работает, как я ожидал.

Вызывающий в обработчике маршрута выглядит так:

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

Функция, которую я вызываю, выглядит так:

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

Что происходит, listInsightPeriods получает данные нормально, но обработчик маршрута не получает их, и я вижу выходные данные отладки обработчика маршрута, прежде чем я увижу выходные данные отладки из listInsightPeriods. Так что я не чувствую, что обработчик маршрута ждет возврата данных.

Любая помощь, которую вы можете предложить, будет замечательной. Я прочитал так много страниц об этом, но до сих пор не могу понять. Спасибо.

Ответы [ 2 ]

1 голос
/ 05 мая 2020

вы можете использовать концепцию «обратного вызова».

обратный вызов потрясающий.

этот код предназначен для вас и я протестировал. все работает нормально.

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)
  // });
}
1 голос
/ 05 мая 2020

Функция toArray также возвращает Promise, поэтому, если вы используете async / await, вы можете попробовать этот подход в своей функции listInsightPeriods

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