Why am I getting ReferenceError: db is not defined - javascript

For some reason I cannot get axios to connect to the DB. Its is a MSQL server and when I use app.get in the server file I can get data returned but when using express DB connection just doesn't persist. In postman I can return a result with all my code on server.js receiving the entire table. This is what I want. When moving everything to axios and routing it to have less code on my server nothing returns anymore. nothing is broken except i get ReferenceError: db is not defined in nodemon.
HomePage
const express = require('express')
const app = express()
const mysql = require('mysql')
const morgan = require('morgan')
//middleware
app.use(express.json())
app.use(morgan('dev'))
//Connect to DB
const db = mysql.createConnection({
user : 'root',
password : '******',
database : 'avengers'
})
db.connect((err) => {
if(err){
console.log(err)
}
console.log('MySql Connected...')
})
//Routes
app.use('/avengers', require('./routes/avengerRouter.js'))
//error handling
app.use((err, req, res, next) => {
console.log(err)
return res.send({errMsg: err.message})
})
app.listen(9000, () => {
console.log("The server is running on port 9000")
})
Server.js
import React, {useState, useEffect} from 'react'
import axios from 'axios'
import AvengersTable from './AvengerTable.js'
function delay(time) {
return new Promise(resolve => setTimeout(resolve, time));
}
export default function Main(){
const [tableState, setTableState] = useState('')
useEffect(() => {
async function getTableData() {
axios.get('/avengers')
await delay(300)
.then(res => {
// setTableState(res.data)
console.log(res)
})
.catch(err => console.log(err.response.data.errMsg))
} getTableData()
}, [])
return (
<div className="Main">
{/* <AvengersTable tableState={tableState}/> */}
</div>
)
}
avengerRouter.js
const express = require('express');
const avengerRouter = express.Router();
function delay(time) {
return new Promise(resolve => setTimeout(resolve, time));
}
avengerRouter
// all data from avengers table http://localhost:9000/avengers
.get('/', (req, res) => {
let sql = 'SELECT * FROM avengers.avengers'
db.query(sql, (err, result) => {
if(err) console.log(err)
console.log(result)
})
})
module.exports = avengerRouter;

Create a file named db.js that includes a DB connection.
const mysql = require('mysql')
const db = mysql.createConnection({
user : 'root',
password : '******',
database : 'avengers'
});
export default db;
Usage of db at top of your HomePage
const db = require('./db.js');
db.connect((err) => {
if(err){
console.log(err)
}
console.log('MySql Connected...')
});
// Other codes goes below
...
And finally usage in your avengerRoute.js
const express = require('express');
const avengerRouter = express.Router();
// Forgotten line here
const db = require('./db.js');
function delay(time) {
return new Promise(resolve => setTimeout(resolve, time));
}
avengerRouter
// all data from avengers table http://localhost:9000/avengers
.get('/', (req, res) => {
let sql = 'SELECT * FROM avengers.avengers'
db.query(sql, (err, result) => {
if(err) console.log(err)
console.log(result)
})
})
module.exports = avengerRouter;

Related

how to fix Error with Nodejs and 'gridfs-stream'

I am trying to follow along a tutorial and use nodejs with 'gridfs-stream' along with a react front end. The tutorial is from last year in 2020.
Here is my code.
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const cors = require('cors')
const multer = require('multer');
const {GridFsStorage} = require('multer-gridfs-storage');
const Grid = require('gridfs-stream');
const path = require('path');
const Pusher = require('pusher')
const mongoPosts = require ('./mongoPosts.js')
// const currentTournamentControllers = require('../controllers/currenttournament-controllers');
const app = express();
const port = process.env.PORT || 9000
app.use(bodyParser.json())
app.use(cors())
const mongoURI = 'mongodb+srv://fbclient:rmbmbkvZVHw3e6OK#cluster0.emaw1.mongodb.net/myFirstDatabase?retryWrites=true&w=majority'
const conn = mongoose.createConnection(mongoURI);
mongoose.connect(mongoURI)
mongoose.connection.once('open', () => {
console.log('DB Connected')
})
let gfs
conn.once('open', () => {
// Init stream
gfs = Grid(conn.db, mongoose.mongo);
gfs.collection('images');
});
const storage = new GridFsStorage({
url: mongoURI,
file: (req, file) => {
return new Promise((resolve, reject) => {{
const filename = `image-${Date.now()}${path.extname(file.originalname)}`
const fileInfo = {
filename: filename,
bucketName: 'images'
}
resolve (fileInfo)
}})
}
})
const upload = multer({storage})
app.get('/', (req, res) => res.status(200).send('hello world'))
app.post('/upload/image', upload.single('file'), (req, res) => {
res.status(201).send(req.file)
})
app.post('/upload/post', (req, res) => {
const dbPost = req.body
console.log(dbPost)
mongoPosts.create(dbPost, (err, data) => {
if(err){
res.status(500).send(err)
} else {
res.status(201).send(data)
}
})
})
app.get('/retrieve/image/single', (req, res) => {
console.log(req.query.name)
gfs.files.findOne({filename: req.query.name}, (err, file) => {
if(err) {
res.status(500).send(err)
} else {
console.log(file)
if(!file || file.length === 0) {
console.log("hi i errored out")
res.status(404).json({err: 'file not found'})
} else {
console.log("hi i am trying to read")
const readstream = gfs.createReadStream(file.filename)
readstream.pipe(res)
}
}
})
})
app.get('/retrieve/posts', (req, res) => {
mongoPosts.find((err, data) => {
if(err){
res.status(500).send(err)
} else {
data.sort((b,a) => {
return a.timestamp - b.timestamp
})
res.status(200).send(data)
}
})
})
app.listen(port, () => console.log(`listening on localhost:${port}`))
The problem is with readstream. When I am trying to retrieve the data it shows the error
TypeError: grid.mongo.ObjectID is not a constructor
I did some debugging and figured out that this can be fixed by changing a value inside the gridfs.js file in the node_modules. The change being suggested on Stack Overflow was this :-
this._store = new grid.mongo.GridStore(grid.db, this.id || new grid.mongo.ObjectID(), this.name, this.mode, options);
changed to
this._store = new grid.mongo.GridStore(grid.db, this.id || new grid.mongo.ObjectId(), this.name, this.mode, options);
The suggestion was to change the grid.mongo.ObjectID value to grid.mongo.ObjectId. So I did that. Now the error coming out is as follows:-
TypeError: grid.mongo.GridStore is not a constructor
For this I am not getting any fixes on stack overflow or any other websites. Can someone please help

How do you send data to socket with different emit?

I want to send data to 2 different components using socket.io, now the first emit works but the second isn't even activated, I tried to invert the order of them inside io.on function and only the first written one works. Is the second waiting for the first emit to end? How can I make them work in parallel?
This is my code:
import {createServer} from "http";
import socketIo from "socket.io";
import express from "express";
import cors from "cors";
import mongoose from "mongoose";
import { MONGODB_URL } from "./config/config";
import jwt from "jsonwebtoken";
import { watchLeaves } from "./database/controllers/LeaveControllers";
import { watchCalendars } from "./database/controllers/calendarControllers";
const port = process.env.PORT || 3333;
mongoose.connect(MONGODB_URL, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
const db = mongoose.connection;
db.on("error", console.error.bind(console, "connection error:"));
db.once("open", () => {
console.log("Connected to database");
});
const app = express();
app.use(cors());
app.get("/", (req, res) => {
res.send({ response: "I am a websocket!" }).status(200);
});
const verifySocketAuth = (header) => new Promise((resolve, reject) => {
if (typeof header !== "undefined") {
const headerArray = header.split(" ")
const token = headerArray[1]
return jwt.verify(token, "Bearer", (err, auth) => {
if (err) reject(new Error(err))
else resolve(auth)
})
}
})
const server = createServer(app);
const io = socketIo(server, {
cors: {
origin: "*",
methods: ["GET", "POST"],
}
});
io.use(async (socket, next) => {
const header = socket.handshake.headers["authorization"];
await verifySocketAuth(header)
console.log("token", await verifySocketAuth(header))
next()
});
const getLeavesAndEmit = async (socket) => {
const lastRecord = await watchLeaves();
socket.emit("FromLeaves", lastRecord);
};
const getCalendarsAndEmit = async (socket) => {
const lastRecord = await watchCalendars();
console.log("last record calendars==>", lastRecord);
socket.emit("FromCalendars", lastRecord);
};
io.on("connection", async (socket) => {
console.log("Client connected");
await getLeavesAndEmit(socket);
await getCalendarsAndEmit(socket);
socket.on("disconnect", () => {
console.log("Client disconnected");
});
});
server.listen(port, () => console.log(`Soket Server listening on ${port}`));
I guess socket.emit doesn't return a Promise, so when you do await getLeavesAndEmit(socket) you are awaiting something that will never resolve. After socket.emit try to return something static from your async function, like return "done"

Cannot read property 'collection' of undefined MongoDB nodejs driver

i'm trying to pass the mongodb connection to all the other routes, so i created another file and imported mongoClient there and wrapped connect and getDb in functions so i can connect to the db first from server.js and then access the db from the other files, but idk why i'm getting Cannot read property 'collection' of undefined
server.js
const express = require('express')
const bodyParser = require('body-parser')
const mongodb = require('./mongodb/db.js')
const auth = require('./routes/auth.js')
require('dotenv').config()
const app = express();
app.use(bodyParser.json());
const PORT = process.env.PORT
app.get('/api', (req, res) => {
res.send('Welcome to the api')
})
app.use('/api/auth', auth);
mongodb.connect(() => {
app.listen(PORT, () => {
console.log(`app is listening at http://localhost:${PORT}`)
})
})
./mongodb/db.js
const MongoClient = require('mongodb').MongoClient;
const DB_URL = process.env.DB_URL
const DB_NAME = process.env.DB_NAME
const dbClient = new MongoClient(DB_URL, { useUnifiedTopology: true })
let db;
const connect = (callback) => {
dbClient.connect().then(client => {
db = client.db(DB_NAME)
console.log("connected to db")
}).catch(console.log)
callback()
}
const get = () => {
return db;
}
module.exports = {
connect,
get
};
./routes/auth.js
const express = require('express')
const router = express.Router();
const db = require('../mongodb/db.js');
const smth = db.get();
console.log(smth) //undefined;
const usersCollection = db.get().collection('users');
const authCollection = db.get().collection('auth')
router.post('/login', async (req, res) => {
...
})
router.post('/register', async (req, res) => {
...
})
module.exports = router
You call callback outside of the promise chain in the connect function of ./mongodb/db.js. It's possible that you are running into some async issues there, as the function can return before the promise chain resolves.

Reusing postgresql pool in other node javascript files

I am creating nodejs backend app with postgresql database. What I want is when once I create connection to database in my db.js file, that I can reuse it in other files to execute queries.
This is my db.js file
const pool = new Pool({
user: 'us',
host: 'localhost',
database: 'db',
password: 'pass',
port: 5432,
})
pool.on('connect', () => {
console.log('connected to the Database');
});
module.exports = () => { return pool; }
And this is how I tried to use it in index.js file
const db = require('./db.js')
app.get('/', (request, response) => {
db().query('SELECT * FROM country'), (error, results) => {
if (error) {
response.send(error)
}
console.log(results)
response.status(201).send(results)
}
})
There aren't any errors, and when I go to this specific page, it's keep loading. Nothing in console also.
But, if I write a function in my db.js file and do something like pool.query(...), export it, and in my index.js I write app.get('/', exportedFunction), everything is working fine.
Is there any way not to write all my (like 50) queries in just one (db.js) file, because I want to organise my project a little bit?
To streamline your project structure entirely, if you're starting from scratch maybe try this :
index.js
const express = require('express');
const app = express();
const PORT = 8080;
const bodyparser = require('body-parser');
const baseRouter = require('../your-router');
app.use(bodyparser.json());
app.use(express.json());
app.use('/', baseRouter);
app.listen(PORT, function () {
console.log('Server is running on PORT:', PORT);
});
your-router.js
const Router = require('express');
const router = Router();
const getCountries = require('../handlers/get');
router.get('/check-live', (req, res) => res.sendStatus(200));
// route for getCountries
router.get('/countries', getCountries);
src/handler/get.js
const YourService = require('./service/your-service');
function getCountries(request, response) {
const yourService = new YourService();
yourService.getCountries(request)
.then((res) => { response.send(res); })
.catch((error) => { response.status(400).send({ message: error.message }) })
}
module.exports = getCountries;
src/service/your-service.js
const connectionPool = require('../util/dbConnect');
class yourService {
getCountries(req) {
return new Promise(((resolve, reject) => {
connectionPool.connect((err, db) => {
if (err) reject(err);
let query = format('SELECT * FROM country'); // get inputs from req
db.query(query, (err, result) => {
if (err) reject(err);
resolve(result);
})
});
}));
}
}
module.exports = yourService;
dbConnect.js
const pgCon = require('pg')
const PGUSER = 'USER'
const PGDATABASE = 'localhost'
let config = {
user: PGUSER,
database: PGDATABASE,
max: 10,
idleTimeoutMillis: 30000
}
let connectionPool = new pgCon.Pool(config);
module.exports = connectionPool;
Please consider this as a basic example, refactor your code to use callbacks/async awaits (in the above example you can just use callbacks not needed to convert into promise), if needed - you can have DB-layer calls from the service layer in order to extract DB methods from the service layer.

No response from node js (mongoose)

I send request from React with:
export const loadItems = () => async dispatch => {
await axios
.get("http://localhost:8000/api/users")
.then(response => {
console.log(response.users);
dispatch(dataLoaded(response.users));
})
.catch(err => {
dispatch(dataLoadFailed(err));
});
};
But there is no response, and the server does not take request, here is my server app code:
server.js
// a lot of requires
const todoRoutes = require("./routes/serverRoute");
const url = "mongodb://localhost:27017/taskManager";
const app = express();
mongoose.Promise = global.Promise;
mongoose.connect(
url,
{ useNewUrlParser: true },
function(err) {
if (err) {
console.log(err);
} else console.log("Database connected");
}
);
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname, "/public/index.html"));
});
// cors allow
app.use("/api", todoRoutes);
app.listen(8000, () => {
console.log("API started");
});
And this is a controller I use, it's all good with Schema and DB, I checked with output to console from the node, users is defined and contains data
const mongoose = require("mongoose");
const User = require("../models/UserModel");
module.exports = {
getUsers(req, res) {
User.find().exec((err, users) => {
if (err) {
console.log(err);
return res.send({ err });
} else {
console.log(users);
return res.send({ users });
}
});
}
};
And this is my router:
module.exports = router => {
router.get('/users', userController.getUsers);
}
Ok, I got it on my own. Problem was here:
router.get('/users', userController.getUsers);
It supposed to be like this:
router.get('/users', userController.getUsers());

Categories

Resources