Mongoose data from server (Nodejs) not displaying / .get() too late - angularjs

I am just wondering if I am doing anything wrong. I save data to mongo like this:
router.route('/userAdditionalData')
//updates current user data
.put(function(req, res, next){
UserAdditionalInfo.findOne({userRef: req.body.userRef}, function(error, foundUser){
if(error){
console.log('Error in adding additional User Data: ', error);
return done(null);
};
if(foundUser){
foundUser.update(req.body, function(error, count){
res.send(200, foundUser)
});
}
else{
var addData = new UserAdditionalInfo();
addData.middleName = req.body.middleName;
addData.employer = req.body.employer;
addData.jobDescription = req.body.jobDescription;
addData.userRef = req.body.userRef;
addData.save(function(error, data){
if(error){
return res.send(500, error)
}
return res.send(200, data);
});
}
});
})
And I get the data like this:
.get(function(req, res){
UserAdditionalInfo.find(function(err, data){
if(err){
return res.send(500, err);
}
return res.send(200, data);
});
});
In my angular controller, when I get the data using $http.get():
$http.get('/api/userAdditionalData').then(function(response){
console.log('response -> ', response.data[0]);
controller.userAdditionalData = response.data[0];
});
The console perfectly logs my response, but when I log the controller.userAdditionalData I get undefined. Now, when I put a $timeout of 10 around my console.log:
$timeout(function(){
console.log(controller.userAdditionalData);
}, 10);
everything works fine. Which means that my data is being set too late. Is there something that I am not doing/doing wrong?

This is beacause the async paradigm in JavaScript. If you make an async call and outside make a log, probably prints undefined because the async is not finished. Wait for the async call with a promise or multiple promises if in a loop, when the promise ends , then you can log the value or use it.

Related

describe-table method using DocumentClient

How to do this request using DocumentClient?
aws dynamodb describe-table --table-name MusicCollection
Document client is for working with items, but assuming you mean how do you do it with Javascript, the answer is like this:
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB.html#describeTable-property
var params = {
TableName: "MusicCollection"
};
dynamodb.describeTable(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});

Handle connection losses: reperform request or resend response

Using angular-sails the sailsjs backend is usually called this way:
this.doSomethingWithItem = function(itemID, callback){
$sails.put('/item/doSomething', {itemID:itemID}).
success(function (data, status, headers, config) {
callback(data);
}).
error(function (data, status, headers, config){
alert('Error!');
});
};
In the backend, most of the Sails (v0.11.0) Controller functions are rather simple. An example might look like such:
doSomething: function(req, res) {
var p = req.params.all();
postgresClientPool.connect(function(err, client, done) {
client.query("SELECT item_do_something_in_this_awesome_function($1) AS dbreturn", [p.itemID], function(err, result) {
done();
if(err) {
res.status(500).json({success: false});
}
else {
res.json(result.rows[0].dbreturn[0]);
}
});
});
}
Now for reasons we can't influence we're experiencing quite frequent but rather short connection losses (between Client/Browser and nodeJS/sails-Server). The task is now to handle them as smooth for the user as possible and avoid any further inconvenience.
So, if during an ongoing request the connection is interrupted, the logic has to be something like:
Check if the connection interruption happened before or after the request reached the server.
If it happened before: re-perform the request.
If it happened afterwards: tell the backend to re-send the result of the request.
Now, how to achieve that?
I don't know if registering a $sails.on('disconnect'... in each service function is the best idea. And anyway, I haven't figured out yet how the de-register them after the function finished executing.
First of all, I would recommend you to separate your business logic out of the controller.
You can check this other answer: sails.js access controller method from controller method
By doing so, you would be able to actually make the call again from the controller, without having to do much.
Also, we will use the async.retry and async.apply functions from the async module.
For example, imagine you move your code to a service in api/services/CustomerService.js ex:
module.exports = {
get: function (customerId, done) {
// postgresClientPool should be available in a param or globally?
// I'd prefer assigning it to the sails object...
// and use it like sails.postgresClientPool
postgresClientPool.connect(function (err, client, release) {
if (err) {
release();
done(err);
}
client.query("SELECT getCustomer($1) AS dbreturn", [customerId],
function (err, result) {
release();
if (err) {
done(err);
} else {
done(undefined, result.rows[0].dbreturn[0]);
}
});
});
}
};
Then, in your controller, for example, api/controllers/Customer.js:
get: function (req, res) {
var p = req.params.all();
async.retry(3, async.apply(CustomerService.get, p.customerID), function (err, result) {
if (err) {
res.status(500).json({
success: false
});
} else {
res.json(result);
}
})
}
You should require async in the top of your controller.

put operation in Node.js

For put request:
router.put('/:id', controller.update);
My update method look like this:
exports.update = function(req, res) {
if(req.body._id) { delete req.body._id; }
Thing.findById(req.params.id, function (err, thing) {
if (err) { return handleError(res, err); }
if(!thing) { return res.status(404).send('Not Found'); }
var updated = _.merge(thing, req.body);
updated.save(function (err) {
if (err) { return handleError(res, err); }
return res.status(200).json(thing);
});
});
};
Making request:
$http.put('/api/things/'+ thing._id, updatedThingObject)
.success(function(update){
console.log("update", update)
})
.error(function(err){
console.log("err", err)
})
It gives connection error on passing the object while making the request in angular.
The error looks like this:
PUT http://localhost:9000/api/things/56c8325b9a0ee7d00d266495
net::ERR_CONNECTION_REFUSED(anonymous function) # angular.js:11442sendReq #
If I take off the updated object, it makes the request just fine but ofcourse nothing gets updated in
that case. What might be wrong here,please?
I figured.
The reason for the functions not being called is that I have a function that is being called repetitively in Node .
var autoCreate = function(){
console.log("THING CREATED AUTOMATICALLY")
var randomNumb=0;
clearTimeout(randomNumb);
randomNumb = (Math.random()* (10-5) + 5).toFixed(0);
console.log("random number", randomNumb)
var randomThing =randomstring({
length: randomNumb,
numeric: false,
letters: true,
special: false
});
console.log("ranfom thing", randomThing)
Thing.create({
name: randomThing,
readByUser: false
}, function(err, thing) {
console.log("THING IS", thing)
//setTimeout(autoCreate, randomNumb * 1000);
});
}
setTimeout(autoCreate, 10*1000);
Since this is running when post/put request is made, I get connection error. How do I handle this to be able to have this function running and be able to make put/post requests as well?

NodeJS - Cannot set headers after they are sent - Multiple Calls

I'm trying to write an app that find a city in a MongoDB collection and uses the latitude and longitude it returns to find all zip codes within a certain distance. It seems to work, but the problem is that I'm getting an error that I can't set headers after they've already been sent. However, I've separated the to routes into different requests I don't understand why I'm still getting this error. What is the best way to make multiple calls to the API?
Here is my router in Node/Express:
// route to get city
app.get('/cities/:zip', function(req, res) {
// use mongoose to get the city in the database
console.log(req.params.zip);
var query = City.find({"zip" : req.params.zip});
query.exec(function(err, city) {
if (err)
res.send(err);
res.json(city);
});
});
// route to find cities within 50 miles
app.get('/matches/:latMin/:latMax/:lonMin/:lonMax', function(req, res) {
console.log(req.params.latMin + req.params.latMax + req.params.lonMin + req.params.lonMax);
var matches = City.find({latitude: {$gt: req.param.latMin, $lt:req.params.latMax }, longitude : {$gt :req.param.lonMin, $lt : req.param.lonMax}});
matches.exec(function(err, match){
if(err)
res.send(err);
console.log(match);
res.json(match);
});
});
app.get('*', function(req, res) {
res.sendfile('./public/views/index.html'); // load our public/index.html file
});
Here is my Angular Controller
$scope.update = function (zip) {
City.get({zip : zip}).success(function(response){
$scope.weather = response
}).then(function(response){
$scope.weather = response.data;
})
if(zip.length = 5){
$http.jsonp('http://api.openweathermap.org/data/2.5/weather?zip='+ zip +',us&callback=JSON_CALLBACK&units=imperial').success(function(data){
$scope.data=data;
});
var box = getBoundingBox([$scope.weather[0].latitude, $scope.weather[0].longitude], 50);
City.matches(box[1], box[3], box[0], box[2]).success(function(response){
$scope.matches = response
}).then(function(response){
$scope.matches = response.data;
console.log($scope.matches);
})
}
res.send does not return; the call continues to res.json. And please use braces. Please. Maybe they don't look cool or whatever. Just use them.
if (err) { handleError(res, err); return; }
res.status(200).json(city);
Further down, keeping things DRY:
function handleError(res, err) {
res.status(500).json(err);
}

Updating database with node.js and angular

I have an app which posts, gets and deletes data and I would like to add 'update' functionality as well but I can't figure it out..
I have a node.js server which has such api:
app.get('/api/feedbacks', function(req, res) {
// use mongoose to get all feedbacks in the database
getfeedbacks(res);
});
// create feedback and send back all feedback after creation
app.post('/api/feedbacks', function(req, res) {
// create a feedback, information comes from AJAX request from Angular
FeedBack.create(req.body, function(err, feedback) {
if (err)
res.send(err);
// get and return all the feedbacks after you create another
getfeedbacks(res);
});
});
// delete a feedback
app.delete('/api/feedbacks/:feedback_id', function(req, res) {
FeedBack.remove({
_id : req.params.feedback_id
}, function(err, feedback) {
if (err)
res.send(err);
getfeedbacks(res);
});
});
and such angular service which speaks to node api:
service.factory('FeedBacks', ['$http',function($http) {
return {
create : function(feedBackData) {
return $http.post('/api/feedbacks', feedBackData);
},
get : function() {
return $http.get('/api/feedbacks');
},
delete : function(id) {
return $http.delete('/api/feedbacks/' + id);
}
}
}]);
That way I can post, get and delete data.
My goal is to add also update function.
What I have tried on node:
// update a feedback
app.put('/api/feedbacks/:feedback_id', function(req, res) {
// edit a feedback, information comes from AJAX request from Angular
FeedBack.put(req.body, function(err, feedback) {
if (err)
res.send(err);
// get and return all the feedbacks after you edit one
getfeedbacks(res);
});
});
on Angular service:
update: function(editFeedId, editedFeed){
return $http.put('/api/feedbacks/' + editFeedId, editedFeed);
}
controller looks like:
$scope.editFeed = function(id) {
$scope.editFeedId = id;
$scope.editedFeed = 'replace this txt'
FeedBacks.update($scope.editFeedId, $scope.editedFeed)
// if successful creation, call our get function to get all the new
feedBacks
.success(function(data) {
console.log('updated');
$scope.feedbacks = data;
});
};
I get 500 error as I execute editFeed(). I couldn't figure out to configure that! Where do I do wrong? Any Tips?
Thanks a lot in advance!
I'm assuming you're using Mongo here, in which case your update statement is incorrect.
It should be something like:
app.put('/api/feedbacks/:feedback_id', function(req, res) {
FeedBack.update({_id: req.params.feedback_id}, req.body, function(err, feedback) {
if (err)
res.send(err);
// get and return all the feedbacks after you edit one
getfeedbacks(res);
});
});

Resources