Getting empty JSON from mongolab after GET request in node - javascript

My problem: I'm trying to HTTP.GET a random questionSchema from my database but it returns "". In my database (that is hosted in mongolab I have a few different collections, but in my questions collection I only have 3 different JSONs with 3 different questions.
I have a Schema that looks like this:
var questionSchema = new Schema({
description: String
});
module.exports = mongoose.model('Question', questionSchema);
In my routes.js I put the following:
app.get('/api/getrandomquestion', function (req, res) {
if (req.params.description) {
res.json(req.description);
} else {
res.json("");
}
});
I also have a service called QuestionService.js which is supposed to query the DB and give me back a random JSON document out of all (3) the documents that exist there. This is the code of the service:
var numberOfItemsToFind = 3;
Question.find({}, { '_id': 1}, function(err, data){
if (err) res.send(err);
var arr = shuffle.(data.slice(0));
arr.splice(numberOfItemsToFind, arr.length - numberOfItemsToFind);
var return_arr = [];
async.each(arr, function(item, callback){
Question.findById(item._id, function(err, data){
if (err) res.send(err);
return_arr.push(data);
callback();
});
}, function(err){
res.json(return_arr);
});
});
And lastly, I put these together with my questionCtrl:
controller('QuestionCtrl', function ($scope, $http, $modal) {
$http.get('/api/getrandomquestion').success(function (question) {
$scope.description = question.description;
});
});
I am using POSTMAN to make a HTTP.GET request to localhost:3000/getrandomquestion and I'm getting back just the "" as I stated.
Any help towards solving my problem (empty JSON instead of a real one) will be greatly appreciated!

The problem is in your routes.js:
app.get('/api/getrandomquestion', function (req, res) {
if (req.params.description) {
res.json(req.description);
} else {
res.json("");
}
});
req.params.description is undefined. So the if statement failed.
If param description is not necessary, You should probably define your GET API like this:
app.get('/api/getrandomquestion', function (req, res) {
QuestionService.getRandomQuestion(function(questions){
res.json(questions);
//res.send(questions);
});
});
Basically your backend receive a GET getrandomquestions API call, you just forward to fetch MongoDB using QuestionService.

Related

How to send data from NodeJS server side to the JS client side, only when data is ready?

On my website, when the user clicks on a button, some user's data will be stored in a database and after that I want the server to send notification data to the Javascript frontend file to change the UI.
Right now, the Js file (index.js) receives data right after the website loads (always false). I want it to be received only when the data is ready on the server.
I searched a lot but couldn't find an answer to my problem?
I appreciate any help :)
server.js
var requestValidation = false;
app.post("/", function(req, res){
var name = req.body.personName;
var email = req.body.personEmail;
var collabTopic = req.body.collabTopic;
const newUser = new User({ //mongoDB schema
name: name,
email: email,
collabTopic: collabTopic
});
newUser.save(function(err){ //adding data to mongoDB
if(!err){
requestValidation = true;
}
});
});
app.get("/succ", function(req, res){
res.json(requestValidation);
});
index.js
const url = "http://localhost:3000/succ";
const getData = async (url) => {
try {
const response = await fetch(url);
const json = await response.json();
console.log(json);
} catch (error) {
console.log(error);
}
};
getData(url);
I'm not sure this is completely the answer you're looking for, but it's definitely a tool/feature to consider as you rework your approach.
app.post("/", async (req, res) => {
let result = await INSERT MONGODB UPDATE OR INSERT FUNCTION;
res.render("YOUR TEMPLATE", result);
});
You probably can't plug and play this, but when you finish a MongoDB operation, it returns a json object with some details on whether or not there was success. For example, a MongoDB insert operation returns something like this (stored in the variable result that I created)
{ "acknowledged" : true, "insertedId" : ObjectId("5fd989674e6b9ceb8665c57d") }
and then you can pass this value on as you wish.
Edit: This is what tkausl referred to in a comment.
Here is an example if you want to pass the content of a txt file to the client with express and jquery:
in express:
app.get('/get', (req, res) => {
fs.readFile('test.txt', (err, data) => {
if (err) throw err;
return res.json(JSON.parse(data));
})
})
jquery in client side:
$.getJSON( "http://localhost:3000/get", function( data ) {
geojsondata1 = JSON.stringify(data)
}
now you can do anything you want with the variable data

Node.js global variable only works once

I have a global variable in my server side code inside a post route and i am trying to access it within another post route. The code executes perfectly when the second post route is called for the first time, but when the second post route is triggered a second time, the value of the global variable becomes undefined.
Snippet of first post route that declares the global variable:
app.post("/login", function(req, res) {
...
fs.readFile('results.json', function (err, data) {
if(err){
console.log(err)
} else{
var json = JSON.parse(data)
...
global.Identifier;
global.Identifier = Identifier;
return global.Identifier;
}
}
);
res.redirect("/");
});
snippet of second post request that accesses global variable:
app.post("/addtask", function(req, res) {
var gloablIdentifier = global.Identifier;
...
res.redirect("/");
};
(When the second post request is accessed a second time, the value of gloablIdentifier = undefined )
NOTE: I understand that using global variables is VERY BAD PRACTICE and should be avoided in most situations at all costs, but I would still like to work on this problem.
Thanks in advance
You did not wait readFile has to be finished and return response. Since, fs.readFile is async, global.Identifier will update later. You can await to read the file and then return;
app.post("/login", function(req, res) {
fs.readFile("results.json", function(err, data) {
if (err) {
console.log(err);
} else {
var json = JSON.parse(data);
global.Identifier = Identifier;
return global.Identifier;
}
// wait for read file
res.redirect("/");
});
// res.redirect("/");
});
async-await version:
const { promisify } = require("util");
const readFile = promisify(fs.readFile);
app.post("/login", async function(req, res) {
try {
const data = await readFile("results.json");
var json = JSON.parse(data);
global.Identifier = Identifier;
return res.redirect("/");
} catch (error) {
return res.redirect("/");
}
});
From the looks of it, you are using something like Express.
Even though this might be a bad practice I think that you should give a try to using the set functionality provided by express itself.
As such, in your app.js do it like this:
app.set("identifier", Identifier)
Then, in your routes:
app.post("/addtask", function(req, res) {
var gloablIdentifier = app.get('identifier')
...
res.redirect("/");
};
I did not test this, it's based on the documentation and on this answer
EDIT: I tested this and it works. Also, to change the variable again just do this on your route:
app.set('identifier', newValue)
I hope the answer is complete now!

Pass data from express route into node module export function

I am new to node, I think I need to use middleware, but I can't warp my head around what it is actually used for, or if this is where it is meant to be used. I have data that is being posted from my view into an express route.
ROUTE - route.js
var GetPlayer = require('./models/getPlayer.js');
module.exports = function(app) {
app.post('/api/getPlayer', function(req, res) {
//GetPlayer.apiGetPlayer(req.body.username);
console.log(req.body.username); //this logs the correct data
});
}
but now I need to pass that data into a node api call and send that response back to the client. But I can not get the route to call that function or pass the data into it.
MODULE.EXPORT - getPlayer.js
module.exports = {
apiGetPlayer: function(error, res) {
console.log("in get player");
console.log(res);
}
}
You would only want to use an Express middleware if this is something you want to do for more than one route (ie. parsing request body's from JSON to actual Object using body-parser). That seems like it could be overkill based on the supplied code. One way to approach this is to just take the username and pass a callback function in to getPlayer. Then when the callback function passed to apiGetPlayer() returns, respond back to the requester based on the result of apiGetPlayer().
getPlayer.js
module.exports =
// callback is an error-first callback function
apiGetPlayer: function(username, callback) {
let err;
let player;
// Logic for getting player go here
// If an error occurs return an error to the callback
if (err)
return callback(err, null);
return callback(null, player);
}
}
/api/getPlayer route
app.post('/api/getPlayer', (req, res) => {
GetPlayer.apiGetPlayer(req.body.username, (err, player) => {
if (err)
return res.status(500).send(err);
return res.status(200).send(player);
});
});

LoopBack: cannot call method 'post' of undefined

I am new to loopback and node.js.
I have created two models: Rating and RatingsAggregate
using the loopback explorer, I can query and post against the API just fine.
I am try to setup some basic business logic so I am editing the file Rating.js in common/models
Here is the content of it:
module.exports = function(Rating) {
Rating.afterRemote('**', function(ctx, inst, next) {
var loopback = require('loopback');
var app = loopback();
var ratingsaggregate = app.models.ratingsaggregate;
ratingsaggregate.post({"source":"foobar","restaurantID":"foobar","itemMenuName":"foobar","itemSectionName":"foobar","itemName":"foobar","nRatings1":123,"nRatings2":123,"nRatings3":123,"nRatings4":123,"nRatings5":123,"hasImage":true,"imageSize":123,"latestImageRatingID":"foobar","imageCount":123,"lastUpdated":"foobar"}, function(err, response) {
if (err) console.error(err);
next();
});
});
};
I can load my API, but whenever I run a get statement against it, I get this error:
TypeError: Cannot call method 'post' of undefined
My guess is that somehow ratingsaggregate never gets a value... but I don't know what I am doing wrong. Obviously this is not the end state of my business logic, but I am trying some basic CRUD right now between two models
And... here is the answer. There was a getModel function hidden in the documentation
module.exports = function(Rating) {
Rating.afterRemote('create', function(ctx, inst, next) {
var loopback = require('loopback');
var ratingsaggregate = loopback.getModel('ratingsaggregate');
ratingsaggregate.create({"source":"foobar","restaurantID":"foobar","itemMenuName":"foobar","itemSectionName":"foobar","itemName":"foobar","nRatings1":123,"nRatings2":123,"nRatings3":123,"nRatings4":123,"nRatings5":123,"hasImage":true,"imageSize":123,"latestImageRatingID":"foobar","imageCount":123,"lastUpdated":"foobar"}, function(err, response) {
if (err) console.error(err);
next();
});
});
};
Fixes everything and the behaviour is the expected one

How to push out requested data from mongodb in node.js

I'm working with Node.js, express, mongodb, and got stuck on this data passing between frontend and backend.
Note: code below is middleware code for front- and backend communication
Here I successfully get the input value from the frontend by using req.body.nr
exports.find_user_post = function(req, res) {
member = new memberModel();
member.desc = req.body.nr;
console.log(req.body.nr);
member.save(function (err) {
res.render('user.jade', );
});
};
Here is the problem, I need to use the input value I got to find the correct data from my database(mongodb in the backend) and push out to the frontend.
My data structure {desc : ''}, the desc is correspond to the input value so it should look something like this {desc: req.body.nr} which is probably incorrect code here?
exports.user = function(req, res){
memberModel.find({desc: req.body.nr}, function(err, docs){
res.render('user.jade', { members: docs });
});
};
Would love to have some help.
Thanks, in advance!
Have a look at this great tutorial from howtonode.org.
Because as you can see he uses a prototype and a function callback:
in articleprovider-mongodb.js
ArticleProvider.prototype.findAll = function(callback) {
this.getCollection(function(error, article_collection) {
if( error ) callback(error)
else {
article_collection.find().toArray(function(error, results) {
if( error ) callback(error)
else callback(null, results)
});
}
});
};
exports.ArticleProvider = ArticleProvider;
in app.js
app.get('/', function(req, res){
articleProvider.findAll( function(error,docs){
res.render('index.jade', {
locals: {
title: 'Blog',
articles:docs
}
});
})
});
Also make sure you have some error checking from the user input as well as from the anybody sending data to the node.js server.
PS: note that the node, express and mongo driver used in the tutorial are a bit older.

Categories