I'm failing to require methods from my ./db/index.js into my server.js file to select data from the database and display it.
The /db/index.js is like this:
'use strict';
const pgp = require('pg-promise')();
const pg = pgp(process.env.DATABASE_URL);
let select = () => {
pg.any('SELECT username, status FROM status')
.then(function(data){
for (var item of data) {
return item.username + "'s status is " + item.status;
}
})
.catch(function(err) {
return 'Error: ' + err.message || err;
});
};
module.exports = () => {
select
};
and I want to call it in from a different file:
'use strict';
const port = process.env.PORT || 3000;
const bodyParser = require('body-parser');
const express = require('express');
const app = express();
const db = require('./db/');
app.use(bodyParser.urlencoded({extended: true}));
app.post('/logdash', function(req, res, next) {
res.status(200).send(db.select());
});
app.listen(port, function() {
console.log('Server is running on port', port);
});
I'm using Heroku, and like this, watching the logs, no error is shown in both terminal and Slack (it's a slash command). I can't find help on how to properly separate the functions. How can I call this select method and any other one from a different file?
There are many problems in your code, some of them listed in the previous answer by #jfriend00.
I will only add that you also do not return any data from the method when it is successful.
Considering how many errors you got there, rather than re-iterating them, I will give you a corrected code example instead.
The database module:
'use strict';
const pgp = require('pg-promise')();
const db = pgp(process.env.DATABASE_URL);
let select = (req, res, next) =>
db.map('SELECT username, status FROM status', null, row=> {
return row.username + "'s status is " + row.status;
})
.then(data=> {
res.status(200).send(data);
})
.catch(err=> {
res.status(500).send(err.message || err);
});
module.exports = {
select
};
And the HTTP service file:
'use strict';
const port = process.env.PORT || 3000;
const bodyParser = require('body-parser');
const express = require('express');
const app = express();
const db = require('./db/');
app.use(bodyParser.urlencoded({extended: true}));
app.post('/logdash', db.select);
app.listen(port, function () {
console.log('Server is running on port', port);
});
The code is based on pg-promise v.4.3.x (upgrade, if you have an older one).
I wouldn't say it is a good approach to organizing your code, but at least it is a working example. You can check out pg-promise-demo for a complete application example that may give you a better idea of how to organize your database code.
API references: map
The code in your module is asynchronous. You can't return a value directly. Instead, you should return the promise and then use the promise from the caller to obtain the final asynchronous value.
For further discussion of this general concept see this answer:
How do I return the response from an asynchronous call?
Change your code to this (see embedded comments):
'use strict';
const pgp = require('pg-promise')();
const pg = pgp(process.env.DATABASE_URL);
let select = () => {
// return the promise here
return pg.any('SELECT username, status FROM status')
.then(function(data){
return data.map(function(item) {
return item.username + "'s status is " + item.status;
});
})
.catch(function(err) {
// to keep this an error, we have to rethrow the error, otherwise
// the rejection is considered "handled" and is not an error
throw 'Error: ' + err.message || err;
});
};
// export the function
module.exports.select = select;
And call it like this:
'use strict';
const port = process.env.PORT || 3000;
const bodyParser = require('body-parser');
const express = require('express');
const app = express();
const db = require('./db/');
app.use(bodyParser.urlencoded({extended: true}));
app.post('/logdash', function(req, res, next) {
db.select().then(function(data) {
res.status(200).json(data);
}).catch(function(err) {
// add some sort of error response here
res.status(500).json(err);
});
});
app.listen(port, function() {
console.log('Server is running on port', port);
});
Summary of changes here:
In select(), return the promise
In the .catch() in select(), rethrow the error to keep it a rejected promise. If you add a handler for a .catch() and don't either rethrow or return a rejected promise, then the error is handled and the promise becomes resolved.
You need to fix your for loop. It should not be doing a return inside the for loop with no conditional checks. That code is probably just wrong (though I'm not sure what you intended to do).
When you call db.select(), use a .then() handler to get teh final resolved value.
Add an error handler for the db.select() promise.
Change the exports so that db.select() is your function.
Revised the way you were referencing data in the for loop so it will actually fetch the desired property.
A few things. I would make sure that your select function returns a Promise. I would also handle the promise in your route. This way you can properly send the appropriate status codes and responses.
db/index.js
'use strict';
const pgp = require('pg-promise')();
const pg = pgp(process.env.DATABASE_URL);
let select = () => {
return pg.any('SELECT username, status FROM status')
}
module.exports = () => {
select
};
server.js
'use strict';
const port = process.env.PORT || 3000;
const bodyParser = require('body-parser');
const express = require('express');
const app = express();
const db = require('./db/');
app.use(bodyParser.urlencoded({extended: true}));
app.post('/logdash', function(req, res, next) {
db.select()
.then((data) => {
res.status(200).json(data)
})
.catch((error) => {
res.status(500).json(error)
})
});
app.listen(port, function() {
console.log('Server is running on port', port);
});
I did not test this, but it should do the trick.
Related
I made this simple example to see how to use the node-cache module. But if I disconnect from node and reconnect the cache gets cleared. Is there a way to make sure the data persists until I clear it? My code is below, thanks for your help.
const express = require('express');
const app = express();
const port = process.env.port || 3000
const NodeCache = require( "node-cache" );
const myCache = new NodeCache();
app.listen(port, (err :boolean)=> {
if (err){
return console.log(err);
}
return console.log(`server is listening on ${port}`);
})
app.get('/', (req, res)=>{
console.log(req.originalUrl);
res.send('I am trying');
})
app.get('/add/:input/:value', (req,res)=>{
let i = req.params.input;
let v = req.params.value;
const success = myCache.set(i, v);
console.log(success);
res.send(`key: ${i} value: ${v}`);
})
app.get('/loop', (req,res)=>{
let mykeys = myCache.keys();
res.send(mykeys);
})
As all my requests are working fine, I have a problem with the put. req.body stays empty and then gives that error :
errmsg: "'$set' is empty. You must specify a field like so: {$set:
{: ...}}"
PUT :
router.put('/books/:name', (req, res, next) => {
const localdb = db.client.db(process.env.DB_NAME);
const collection = localdb.collection(process.env.COLL_BOOKS);
collection.replaceOne(
{ "name": req.params.name },
{ $set: req.body },
function (err) {
if (err) throw err
res.status(201).send(true);
});
App.js
const express = require('express'),
app = express();
os = require('os');
const bodyParser = require('body-parser');
const cors = require('cors');
const router = require('./router.js')
require('dotenv').config()
app.use(cors());
app.use(bodyParser.json());
app.use('/api/v1', router);
const port = (process.env.PORT || '3001');
let server = app.listen(port, os.hostname(), () => {
let host = server.address().address,
port = server.address().port;
console.log("Example app listening at http://%s:%s", host, port);
});
axios request :
updateItem = newBook => {
Axios.put(process.env.REACT_APP_API_PATH_BOOKS + `${newBook.name}`, newBook)
.then(res => {
this.setState({ newBook: res.data });
this.props.history.push('/admin');
})
.catch(err => console.log(err));
}
I don't understand what I am doing wrong
Make sure you don't have any middlware stripping or incorrectly parsing the body. For instance, you may have a JSON body parser, and not be sending JSON data with JSON application headers.
Can you give a bit of context, in code, for how you are making the put request and also the result of logging the req in a pastebin?
I have a React app that uses express in the backend. I try to get from my db a list of messages through a fetch API call.
The code in the Frontend:
App.js
getMessages = () => {
fetch('/api/mess')
.then(res => res.json())
.then(res => {
var Messages = res.map(r => r.messages);
this.setState({ Messages });
});
};
The code in the backend:
api/mess.js
var express = require('express');
var Mess = require('../queries/mess');
var router = express.Router();
router.get('/', (req, res) => {
Mess.retrieveAll((err, messages) => {
if (err)
return res.json(err);
return res.json(messages);
})
});
router.post('/', (req, res) => {
var message = req.body.message;
Mess.insert(message, (err, result) => {
if (err)
return res.json(err);
return res.json(result);
});
});
module.exports = router;
queries/mess.js
const db = require('../database');
class Mess {
static retrieveAll(callback) {
db.query('SELECT * FROM mess;', (err, res) => {
if (err.error)
return callback(err);
callback(res);
});
}
static insert(mess, callback) {
db.query('INSERT INTO mess (messages) VALUES ($1)', [mess], (err, res) => {
if (err.error)
return callback(err);
callback(res);
});
}
}
module.exports = Mess;
index.js
const path = require('path');
const express = require('express');
const bodyParser = require('body-parser');
var db = require('./database');
const ENV = process.env.NODE_ENV;
const PORT = process.env.PORT || 3011;
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use('/api/mess', require('./api/mess'));
app.use('/api/roles', require('./api/roles'));
app.listen(PORT, () => {
console.log(`Server listening on port ${PORT}...`);
});
module.exports = app;
I get this error on my Frontend:
SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
I have tried and changed every response and request to use either JSON.parse or .json and I get the same message no matter what.
When I use my browser and go to the api channel I get a correctly formatted JSON with the contents of the db.
Did I miss something?
EDIT:
The stack trace is super minimal:
When I try:
getMessages = () => {
fetch('/api/mess')
.then(res => console.log(res));
};
I get this object:
The problem is that the backend is at PORT 3011 and the api call is made to PORT 3000 from the frontend.
I need to have a proxy to point from the forntend to the backend port.
I need to add inside client/package.json (Frontend) this line:
"proxy": "http://localhost/3011"
I was just trying to create a simple Express app and trying to save data using MongoDB. Everything went fine until I tried to add the status code. I've tried adding the status code using 3 different methods but nothing seems to work.
Using Express 4.14.1
const express = require('express');
const bodyParser = require('body-parser');
const {mongoose} = require('./db/mongoose');
var {Todo} = require('./models/todo');
var {User} = require('./models/user');
var app = express();
app.use(bodyParser.json());
app.post('/todos', (req,res) => {
console.log(req.body);
var todo = new Todo({
text: req.body.text
})
todo.save().then( (doc) => {
res.send("Doc saved : ", doc);
}, (error) => {
res.status(400).send(error)
})
})
app.listen(3000, () => {
console.log("Listening on port 3000")
});
Can you attach the error you are getting?
Have you tried this save method? I'm wondering if your save is not working.
todo.save((err, todoresult) => {
if (err) {
console.log('error saving to user: ', err)
return res.json(err)
} else {
res.json(todoresult);
}
});
I am using supertest to test get requests to mLab app. If I do a regular GET request with postman I receive this:
{"_id":"5b169a9951573c50d9682d52","text":"First test note","title":"Test1"}
But the response received in the test adds slashes before each quote:
{\\"_id\\":\\"5b169a9951573c50d9682d52\\",\\"text\\":\\"First test note\\",\\"title\\":\\"Test1\\"}
This is my test file:
const server = require("../../app/server");
const request = require("supertest")(server);
describe("routes: index", () => {
test("should respond as expected", async() => {
const app = request("http://localhost:8000");
const response = await app.get("/notes/5b169a9951573c50d9682d52");
expect(response).toEqual("First test note");
expect(response).toEqual("Test1");
});
});
This is my server
const express = require('express'); // node module
const MongoClient = require('mongodb').MongoClient;
const bodyParser = require('body-parser');
const db = require('./config/db');
const app = express();
const port = process.env.PORT || 8000;
app.use(bodyParser.urlencoded({
extended: true
}));
MongoClient.connect(db.testUrl, (err, database) => {
if (err) return console.log(err)
require('./routes')(app, database);
app.listen(port, () => {
console.log('We are live on ' + port);
console.log(process.env.PORT);
});
})
module.exports = app;
I haven't been using supertest myself, but a brief look at your code and documentation immediately shows several issues.
First of all, what you see is what your test framework reports to you - it is a string representation of the json object. It is correct.
What is not correct is how you try to handle the response. Check the documentation:
https://www.npmjs.com/package/supertest
I think, you may solve the problem by
1) setting the expected type
2) and by accessing the body member of the response
const response = await app.get("/notes/5b169a9951573c50d9682d52").set('Accept', 'application/json');
expect(response.body.text).toEqual("First test note");
I hope, this works.