Reputation: 12409
I'm a long time programmer (mostly Java) but new to 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().
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. In other words, I need to run the function then return control with results back to the router. 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.
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:
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. 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.
Upvotes: 0
Views: 46
Reputation: 828
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)
// });
}
Upvotes: 1
Reputation: 94
The toArray function also returns a Promise, so if you're using async/await you can try this approach in your 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;
}
Upvotes: 2