Use a class method in router.get - javascript

I'm really new to node.js
and I'm having trouble when I'm using a class method in router.get callback
It gives me this error:
Can you guys help me out ?
Route.get() requires a callback function but got a [object object]
Here is my code
router.js :
const express = require('express');
const router = express.Router();
const test = require('../controller/controller');
router.get('/', test.testing());
module.exports = router;
controller.js :
class oop
{
testing(req,res)
{
console.log('okay');
}
}
exports.testing =new oop();
app.js :
const express = require('express');
const app = express();
app.listen(80);
const wiki = require('./routes/router');
app.use('/', wiki);

A callback function will be called in some arbitrary amount of time, therefore you need to provide a reference to the function... so when the time comes, Javascript can execute that function. In your case, you are not passing the function, but running it! test.testing(). What you are actually passing to the 'callback' parameter is the result of test.testing() which, in this case, is undefined

Related

Best Practice for Route Architecture

I'm trying to set up routes for my backend. I have two ways that I've tried setting these routes up, and I'm wondering which way fits best practices (or neither?). The differences are minimal, but I'd love to know if there is an objective "best" here.
Here are my attempts:
const express = require("express");
const router = express.Router();
const flashcardController = require('../controllers/flashcardController');
router.get('/', flashcardController.readFlashcard);
router.post('/', flashcardController.createFlashcard);
router.patch('/', flashcardController.updateFlashcard);
router.delete('/', flashcardController.deleteFlashcard);
module.exports = router
VS
const express = require("express");
const router = express.Router();
const flashcardController = require('../controllers/flashcardController');
module.exports = (app) => {
router.get('/api/flashcard', flashcardController.readFlashcard);
router.post('/api/flashcard', flashcardController.createFlashcard);
router.patch('/api/flashcard', flashcardController.updateFlashcard);
router.delete('/api/flashcard', flashcardController.deleteFlashcard);
app.use('/', router);
};
Of course, my app.js (entry-point for my backend) file will need to be coded slightly differently for each of these options.
If you believe that the job of a router is to just handle some requests that it receives and it is the job of the calling code to place the router at whatever path the calling code wants it to operate on, then only your first option will do that. This would allow a caller to use these routes in whatever path it wants.
If you want the module that implements the routes to be entirely self-sufficient and install the routes on the path it wants them to be on, then only the second option does that.
I would say that the "usual" and more "flexible" scheme is the first one where the caller places the routes on the path where it wants them. But, you are free to choose whichever style you want.
The second option is not implemented particularly efficiently so it could be improved. No router is needed at all as the routes can be just installed directly on the app object directly. And, repeating /api/flashcard multiple times can be avoided.
For example, the second option could be this:
const controller = require('../controllers/flashcardController');
const routePath = '/api/flashcard';
module.exports = (app) => {
app.get(routePath, controller.readFlashcard);
app.post(routePath, controller.createFlashcard);
app.patch(routePath, controller.updateFlashcard);
app.delete(routePath, controller.deleteFlashcard);
};
Or, even just this:
const controller = require('../controllers/flashcardController');
module.exports = (app) => {
app.route('/api/flashcard')
.get(controller.readFlashcard)
.post(controller.createFlashcard)
.patch(controller.updateFlashcard)
.delete(controller.deleteFlashcard);
};
And, the first one could be simplified to this:
const router = require("express").Router();
const controller = require('../controllers/flashcardController');
router.route('/')
.get(controller.readFlashcard)
.post(controller.createFlashcard)
.patch(controller.updateFlashcard)
.delete(controller.deleteFlashcard);
module.exports = router

How does the const a = express() works exactly?

I recently started learning Node/express. One doubt is bugging me for a couple of weeks now. I know what this does, and I've been able to get past it. But I cannot wrap my head around the logic used in the line const a = express().
express = require('express');
const a = express()
I don't think I have seen this before in javascript. In this case, express is an object or function (functions are also object in JavaScript) right? And this line is what gives the variable a access to lots of important methods like listen() and get(). But doesn't the syntax here is wrong? To use the express() function, we need to write like
const express = require('express');
const a = express.express()
or we need to use object destructuring to write like
const {express} = require('express');
const a = express()
Perhaps the confusion is in assuming that the default export of the express module is something other than a function, but as others have pointed out, the default export of express is a function. Once imported, the returned value of that function is an instance of Express which is where you then have access to all those methods you mentioned.
Imagine that the definition of function express and the object it returns looks something like
class Express {
// Implementation of Express server
}
// You're importing this and calling the function, receiving a new instance of this class. In reality this could be a class or object for all I know.
export default function express() {
return new Express()
}

not able to acces db() from exported MongoClient module

I am not able to export the client properly from db.js to User.js
db.js
const some= MongoClient.connect(process.env.CONNECTIONSTRING).then((client) =>{
module.exports=client
const app = require("./app")
app.listen(process.env.PORT)
})
Using the client here , i can do methods like client.db().collection("users");
But i am not able to do using the user.js
User.js
const usersCollection = require("../db").db().collection("users");
This gives error saying const
usersCollection = require("../db").db().collection("users");
^
TypeError: require(...).db is not a function
I maybe wrong but in the callback function for MongoClient the first argument is the error and second argument is for client.(err,client)
so you are calling db() on error and not client
And also try to export from global scope as mentioned by Maxime in the comment
You have this problem because you are importing something that is asynchronous and when you do it in 1 line the client is not ready when you try to call it with db().collection("users").
You can verify if the async is the issue by changing your code to this:
const temp = require("../db")
setTimeout(() => {
temp.db().collection("users")
}, 1000)
You can also check here for an example how to do the connection to the DB properly https://www.terlici.com/2015/04/03/mongodb-node-express.html

Running Code When a Module is Loaded and Exposing It as Middleware

I am still trying to fully understand how exporting and importing modules works in Nodejs.
I am using the following file to seed a mongodb database. This file runs exactly as it should and returns exactly the result I am expecting, when I execute it as a standalone file. My issue is I want to use this file in two different places in my app. So I am trying to make it an exportable/importable module. Here is what I have tried:
seed.js looks like this:
'use strict';
// library modules
const {ObjectID} = require('mongodb');
const seeder = require('mongoose-seed');
const jwt = require('jsonwebtoken');
const util = require('util');
// local modules
const {Course} = require('./../models/course');
const {Review} = require('./../models/review');
const {User} = require('./../models/user');
const {data} = require('./../data/data.js');
const config = require('./../config/config.js');
/*==================================================
build seeding Courses, Reviews, Users
==================================================*/
// Connect to MongoDB via Mongoose
let seed = seeder.connect(process.env.MONGODB_URI, (e) => {
console.log(`Connected to: ${process.env.MONGODB_URI} and seeding files`);
// Load Mongoose models
seeder.loadModels([
'src/models/user.js',
'src/models/review.js',
'src/models/course.js'
]);
// Clear specified collections
seeder.clearModels(['User', 'Review', 'Course'], function() {
// Callback to populate DB once collections have been cleared
seeder.populateModels(data, function() {
seeder.disconnect();
});
});
});
module.exports = seed;
Within app.js I have these two lines
const seed = require('./middleware/seed');
and
app.use(seed);
I have also tried, to no avail
app.use(seed());
What is missing? I don't want to use the code in-line in two different places (DRY you know).
It is failing with this error:
throw new TypeError('app.use() requires a middleware function')
I am sorry about the formatting I thought I was using markdown, but I am clearly not.
You are executing your seeder function in that module and not returning any middleware function at all. Middleware is always a function and it has the form of:
const seed = function (req, res, next) {
...
next()
}
With what you have now, the best you can do is the following which will certainly seed your models when the module is loaded.
const seed = require('./middleware/seed');
Are you trying to run those two functions as middleware, on every request? In that case you'd do something like this:
const seed = function (req, res, next) {
seeder.connect(..., (e) => {
...
seeder.clearModels(..., ()=>{
...
next()
})
})
})
If you want to run that seeder code at the module level AND to expose it as middleware then wrap the current module level code in function and execute it when the module loads. Notice that the new function optionally handles the next callback if it receives it.
function doSeed(next){
//your code currently running at module level
if(next)
return next()
}
doSeed(); //run the code at the module level
const seed = (req, res, next) => doSeed(next))
module.exports = seed;
One way that I allow myself to have access to a variable in different instances is adding it to the process variable. In node.js no matter where in the project it is, it will always be the same. In some cases, I would do process.DB = seed(); which would allow process.DB to always be the result of that. So inside your main class you can do process.DB = seed(); and all of your other classes running off of that one main class would have access to process.DB keeping your database readily available.

Express - Accessing top-level express function through dot-notation

In a simple javascript file, we can use express by adding these two lines of code at the beginning (after installing it through npm):
var foo = require('express');
var app = foo();
Now, according to the express API guide:
The app object conventionally denotes the Express application. Create it by calling the top-level express() function exported by the Express module
Since the app object is calling the top-level express() function, how come am I not able to just simply use:
var app = foo.express();
The first line assigns whatever the module 'express' exports to a variable named express. Different modules will export different things (objects, functions). Express exports a function.
The line:
var app = express()
executes the function. This function generates the express application object. This object has all the methods that you use to handle requests in your standard express apps.
The require function that was passed 'express' returns module.exports, which holds the top level function express(), something similar to:
module.exports = express(){...}
That is why we still need to call it either through:
var foo = require('express');
var app = foo();
or
var app = require('express')();
You cannot use:
var foo = require('express');
var app = foo.express();
because it was not set up that way, you could use it if the express module looked something like this:
module.exports.express = express(){...}
I don't know the reason as to why you would choose one over the other, I only know that the second technique simply exposes your function directly.

Categories