I am new to Node.js and javascript. I have a problem which I can't solve. I have a Node application, also I am using Express.
My problem: I have a script that sends a JSON to my server. This data is then stored in my MongoDB. What i want to do now is display that data on another page. This is what i have:
router.post('/', function(req, res, next) {
MongoClient.connect(url, function(err, db) {
var dbase = db.db("db");
dbase.collection('db').insertOne(req.body, function (err, result) {
if (err)
console.log('error');
else
console.log('success');
res.render('result');
});
});
});
What would be the best way to display the data stored in req.body? And could I send it to 'result'? Or should I display the data within the InsertOne-Function?
Please read the express documentation for all the details.
The JSON response can be sent using res.json() method.
Your code will look like this -
router.post('/', function(req, res, next) {
MongoClient.connect(url, function(err, db) {
var dbase = db.db("db");
dbase.collection('db').insertOne(req.body, function (err, result) {
if (err)
console.log('error');
else
res.json(result);
});
});
});
Related
I am fetching data from a MongoDB database then putting it in a cursor to send that as a Node.js response.
var router = express.Router();
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost/EmployeeDB';
/* GET users listing. */
router.get('/', function(req, res, next) {
//res.send('respond with a resource');
MongoClient.connect(url, function(err, db) {
var cursor = db.collection('Employee').find();
cursor.each(function(err, doc) {
console.log(doc);
arrayres = doc ;
res.send(doc);
});
db.close();
});
});
module.exports = router;
It sends only the first record then I get this error:
Error [ERR_HTTP_HEADERS_SENT]: Cannot remove headers after they are sent to the client
at ServerResponse.removeHeader (_http_outgoing.js:528:11)
at ServerResponse.send
Notice: I get this error only when there are multiple records to send as response.
You are sending the response twice. Which is impossible ( look at Why can't we do multiple response.send in Express.js? )
res.send('respond with a resource');
Here and
res.send(arrayres);
Here.
Here is a working example based on jeremy's answer :
router.get('/', function (req, res, next) {
MongoClient.connect(url, function (err, db) {
var cursor = db.collection('Employee').find();
let employees = []
const pushData = async () => {
cursor.forEeach( function (doc) {
employees.push(doc);
});
}
const sendResponse = async () => {
await pushData();
res.json(employees);
}
});
});
You can only send back one response to the browser (be it res.send(), res.end(), res.sendFile(), res.json() or any other). So, you can't have that inside a .forEach().
First, build an array, then send your data back once.
router.get('/', function (req, res, next) {
MongoClient.connect(url, function (err, db) {
var cursor = db.collection('Employee').find();
let employees = []
cursor.forEeach( function (doc) {
employees.push(doc);
});
res.json(employees);
});
});
Or with Mongoose :
Employee.find().lean().exec( (err,docs) => res.json(docs))
I'm starting with Express and I have a question; I have the setup and everything, I've made some simple things but know I want to interact with an API, to do what I want to do I need to the data that I want to get it's from an input field. I want to refresh the main (/) page with the data that was sent. Like a client-side ajax request. I don't know how to send the data that was sent to the post router to the get router without having to go to another link (i.e. localhost:3000/link), i want to stay in the same page where the request was done. I'm using pug (jade) in the template
Express:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', (req, res, next) => {
res.render('index');
});
/* POST HANDLER */
router.post('/link', function(req, res, next) {
console.log(req.body);
});
module.exports = router;
jQuery:
$('#shortLink').on('click', () => {
$.ajax({
type: 'POST',
url: '/link',
data: $('linkInput').val()
});
});
So, to be clear. User puts something on the input field; sends that data to the post router, I want to get the information sent to the post router to be sent to the get router without having to leave the page where the request was done. Let me know if I didn't explain myself very well.
Let's just say you have the body parser set up and understand how does the templating work.
In this what you want is to somehow save the data somewhere on the server. Now in a very simple case you can just save it to variable:
var data = null;
router.get('/', (req, res, next) => {
res.render('index', { data: null });
});
router.post('/link', function(req, res, next) {
data = req.body
res.send('');
});
Then in your template you can do p= data.
Now after you post to the /link then on the next refresh / will show the data.
In most web applications though, people will save these things to the database. Here's an example for MongoDB saving the data to specific document:
router.get('/', (req, res, next) => {
collection.findOne({ id: 'specificDoc'}, function (err, result) {
if (err) {
next(err);
return;
}
res.render('index', { data: result.data });
});
});
router.post('/link', function(req, res, next) {
collection.update({ id: 'specificDoc', { data: req.data }, { upsert: true }, function (err, result) {
if (err) {
next(err);
return;
}
res.send('');
});
});
Probably you might also start using sessions and save the data depending on the user using cookies or other methods. Here's a toturial for using sessions in express.
So I have a MongoDB that I query using Node.js.
The data is not being sent out using this function and I dont know what is wrong
var findIco = function(db, callback) {
var cursor =db.collection('footIco').find();
cursor.each(function(err, doc) {
// console.log(err);
if (doc != null) {
console.log(doc); <------ DISPLAY THE DATA IN THE CONSOLE
} else {
callback();
}
});
};
app.get('/icons', function(req, res){
//calling the function
MongoClient.connect(url, function(err, db) {
if(err) {
console.log(err);
return res.status(500).send(err);
}
findIco(db, function(icons) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type");
console.log(icons);<--------------- IS UNDEFINED
res.json(icons);
db.close();
return;
});
});
});
app.listen(8080);
What am I doing wrong?
You would need to use some form of Web Server to create an API that will return this data when a request is received at a certain resource. You can make the requests to your API using the $http service in your Angular app. The most popular choice for a Node web framework is Express, this wraps the Node Core HTTP Module and gives a robust API.
Other Popular Node.js Web Frameworks
Koa
Hapi.js
These are just a couple of Node.js Web Frameworks, I also excluded any frameworks that are MVC based frameworks such as Meteor and Sails.js since Angular already is providing that piece.
To get up and running quickly in Express, you can use express-generator to scaffold out a basic Express API. Then just add a route for your function in your Node.js server.
findIco
var findIco = function(db, callback) {
db.collection('footIco').find().toArray(function(err, docs) {
if (err) return callback(err, null);
return callback(null, docs);
});
}
Node.js API
app.get('/icons', function getIcons(req, res){
//calling the function
MongoClient.connect(url, function(err, db) {
if(err) {
console.log(err);
return res.status(500).json(err);
}
findIco(db, function(err, icons) {
if (err)
res.status(500).json(err);
else {
if (!icons)
res.status(204).send();
else
res.json(icons);
}
db.close();
return;
});
});
});
Angular $http call in footIconCtrl
app.controller('footIconCtrl', ['$scope', '$http', function($scope, $http){
$scope.icons = [];
$http({
method: 'GET',
url: 'http://<serverAddress>:<serverPort>/icons'
})
.then(function(icons) {
$scope.icons = icons.data;
})
.catch(function(errRes) {
// Handle errRess
});
});
In your angular code, you will have a file like getDocument.controller.js with a function with an http call to your service. Something like this :
var getDocs = function(){
var apis = http://localhost:9000/api/getDocs;
httpRequest.get(apis).
then(function(docs){
// Your code to handle the response
});
};
Now in your server side code, you can send the response as
CollectionName.find({}, function (err, docs) {
if (err) return next(err);
if (!docs) return res.send(401);
res.json(docs);
});
I'm trying to load JSON from a URL to a variable and send it back to the client's javascript
var getJSON =require('get-json');
app.post('/json', function(req, res) {
getJSON(url, function(err, res){
if(err)
{
console.log(err);
}
else
{
res.setHeader('content-type', 'application/json');
res.send(JSON.stringify({json: res.result}));
}
});
});
Every time I run the code the server says that res.setHeader isn't a function and the rest breaks.
Both post and getJSON callbacks have same res variable name.
Try this:
var getJSON =require('get-json');
app.post('/json', function(req, res) {
getJSON(url, function(err, response){
if(err)
{
console.log(err);
}
else
{
res.setHeader('content-type', 'application/json');
res.send(JSON.stringify({json: response.result}));
}
});
});
for me this was happening when fetching data in a forum i built. i found the fix to this in this blogpost:
https://dev.to/shailesh6363/facing-error-res-setheader-not-a-function-2oc9
i added code according to atul singh in the comments.
changes in app.js
app.use((res, next) => {
....
});
to
app.use((req, res, next) => {
....
});
now the app doesnt crash and it sucessfully fetches and displays the data
I'm trying to generate a page with the post connected to an id, I've got the id in to the node function witch I can see in the console but i don't know how i can render a new view with this posts content?
thankful for all ideas!
i think something is wrong with the search do to the fact that I don't get the item value in the console
in my node js file
router.param('id', function(req,res, next, id){
console.log(req.params.id)
db.collection('insights').find({_id:req.params.id}).toArray(function (err, items) {
res.json(items);
console.log(items)
});
res.send(items);
});
router.get('/share/:id', function(req, res) {
res.render('contact');
});
The param() callback is generally not for directly responding to requests (although maybe in case of error). It's to be used for loading data from databases, etc.
Here's what you might do:
router.param('id', function(req, res, next, id) {
db.collection('insights')
.find({_id: id})
.toArray(function(err, items) {
if (err) {
console.error(err);
return res.send(404);
}
req._items = items;
next();
});
});
router.get('/share/:id', function(req, res) {
res.render('contact', { items: req._items });
});