Breaking Down Callback Functions Based on Previous Variables
I am trying to figure out how to efficiently break down callback functions that depend on variables defined earlier in the code. Currently, my code resembles a "callback hell" due to my lack of knowledge on organizing and breaking down callbacks effectively.
Prerequisite
Take a look at this snippet using a long callback function:
MongoClient.connect(
process.env.MONGODBINST,
(err, db) => {
assert.equal(null, err)
console.log("Connected successfully to database.")
app.get(
"/",
(req, res) => {
res.sendFile(path.join(__dirname + "./../public/index.html"))
}
)
app.get(
"/api/AmountIssuesOpen",
async (req, res) => {
const issuesOpen = await db.collection("GHISSUES")
.find({"state": "open"})
.count()
res.send({issuesOpen})
}
)
}
)
How can I separate the individual routes (app.get()
) from each other? Let's explore different scenarios.
Situation 1: Breaking Down the Full Callback (working example)
const entireCallback = (err, db) => {
assert.equal(null, err)
console.log("Connected successfully to database.")
app.get(
"/",
(req, res) => {
res.sendFile(path.join(__dirname + "./../public/index.html"))
}
)
app.get(
"/api/AmountIssuesOpen",
async (req, res) => {
const issuesOpen = await db.collection("GHISSUES")
.find({"state": "open"})
.count()
res.send({issuesOpen})
}
)
}
MongoClient.connect(
process.env.MONGODBINST,
entireCallback
)
Situation 2: Attempting Further Breakdown (limitations)
However, breaking it down into smaller functions becomes challenging as the second route /api/AmountIssuesOpen
relies on the variable db
.
const _indexRoute = (req, res) => {
res.sendFile(path.join(__dirname + "./../public/index.html"))
}
const _AmountIssuesOpenRoute = async (req, res) => {
const issuesOpen = await db.collection("GHISSUES")
.find({"state": "open"})
.count()
res.send({issuesOpen})
}
const entireCallback = (err, db) => {
assert.equal(null, err)
console.log("Connected successfully to database.")
// This works because the index Route doesn't need `db`
app.get(
"/",
_indexRoute
)
// Issue arises as `db` is undefined here
app.get(
"/api/AmountIssuesOpen",
_AmountIssuesOpenRoute
)
}
MongoClient.connect(
process.env.MONGODBINST,
entireCallback
)
The problem with _AmountIssuesOpenRoute
is that db
is not defined. Passing db
as an argument also doesn't resolve the issue:
const _AmountIssuesOpenRoute = async (req, res, db) => {
const issuesOpen = await db.collection("GHISSUES")
.find({"state": "open"})
.count()
res.send({issuesOpen})
}
Situation 3: Isolating the app.get() Routes?
Is it feasible to separate the entire app.get()
functions? How could they be contained in another file and simply passed into the MongoClient.connect()
callback?
const _completeIndexRoute = () => {
app.get(
"/",
(req, res) => {
res.sendFile(path.join(__dirname + "./../public/index.html"))
}
)
}
const _completeAmountIssuesOpenRoute = () => {
app.get(
"/api/AmountIssuesOpen",
async (req, res) => {
const issuesOpen = await db.collection("GHISSUES")
.find({"state": "open"})
.count()
res.send({issuesOpen})
}
)
}
const entireCallback = (err, db) => {
assert.equal(null, err)
console.log("Connected successfully to database.")
_completeIndexRoute
_competeAmountIssuesOpenRoute
}
MongoClient.connect(
process.env.MONGODBINST,
entireCallback
)