confused with facebook json object with jquery and nodejs - facebook

writing my first facebook/node/express app
With express I'm using
app.post('/friends', function(req, res) {
graph.get("/me/friends?fields=id,name", function(err, res2) {
res.send(res2);
});
});
client side I'm using
$('#getFriends').click(function() {
$.post('/friends', function(data) {
console.log(data);
console.log(data.length);
});
});
With a previous app, I called the graph from the client side with getJSON and looped through everything with a for loop to print out the id and name. With this, I'm confused. Do I need to convert it to an array or a string first? Am I using the express request properly?
It logs the data object, but even when I go to print the length it's null.

Related

Axios Delete Not Working In React App But Working In PostMan/Insomnia

Axios DELETE works when I send a request through postman but on my react app it doesn't. I'm passing the _id that MongoDB assigns the entry. I'm initiating ObjectId and it still doesn't work. I also double checked if I was using the correct route, which I was.
In my app I have click function that calls SaveBook. That part I feel okay about. Let me know if I need to share something else.
SaveBook in AuthActions.js on the front end
export const saveBook = ({books, user, book, _id}) => {
return function () {
console.log(`This is id ${JSON.stringify(_id)}`)
const savedIndex = books.indexOf(book);
if (savedIndex >= 0) {
console.log(savedIndex)
axios
.delete("/api/users/wishlist", {_id})
} else {
console.log(savedIndex)
// console.log(`Adding ${book.book.title} to faves...`);
axios
.post("/api/users/dashboard", {book, user})
.then(console.log("success"))
.catch (err =>
json(err)
);
}
}
};
In users.js the delete operation on the server side
router.delete('/wishlist', (req, res) => {
const db = mongoUtil.getDb();
db.db("mern-auth-2").collection("savedbooks")
.deleteOne({_id:ObjectId(req.body._id)})
.then(res.json(res.data))
});
I realized req.body wasn't the correct choice for the Delete method and used url params/ req.params to send the _id. This works well.
Fixed this line in authActions.js
axios
.delete("/api/users/wishlist/" + _id,)
Fixed these few lines in Users.js
router.delete('/wishlist/:id', (req, res) => {
const db = mongoUtil.getDb();
db.db("mern-auth-2").collection("savedbooks")
// .deleteOne({_id:ObjectId(req.body._id)})
.deleteOne({_id:ObjectId(req.params.id)})

MongoDB: can't return random document from collection

I'm working on a word game and am trying to return a random wordpair (my collection) on a page load. I'm using Express and have adapted my code from this tutorial if that's of any use.
A GET request renders my page just fine, and I'm trying to send a random WordPair object alongside the title:
router.get('/', function(req, res, next) {
res.render('play', { title: 'play', random_wordpair: wordpair_controller.wordpair_random});
});
The wordpair_random function is here inside a controller file I've made (which also successfully manages listing the wordpairs and creating new ones etc).
// Get random WordPair
exports.wordpair_random = function() {
WordPair.aggregate(
[{
$sample: {
size: 1
}
}]
)
.exec(function(err, random_wordpair) {
if (err) {
return next(err);
}
console.log(random_wordpair);
return random_wordpair;
});
};
Then inside a play.pug template, I'm simply trying to display this result:
h3 random wordpair selection is: #{random_wordpair}
But all I can see is the function rendered as HTML text. Can anyone tell me what I'm doing wrong?
I also understand looking at the documentation for MongoDB $sample aggregation that I need to be calling my function on the database object, but I've seen various examples and some don't do this. When I try calling db.wordpair.aggregate(...) (or WordPair or wordpairs as it appears in mLab) directly after initializing db in my app.js file, I get undefined errors. My db object doesn't seem to contain the correct data for this request.
Thanks!
I guess you're writing this in Node.JS. A core feature in Node.JS is non-blocking IO model. That means, the code won't wait for a database call to complete to move on.
Another concept you need to get it right is that Node.JS, being a variation of JavaScript, in nature is a functional programming. Assigning a function to a property of a JSON object like below won't cause the function to execute. It simply creates a pointer to the function body, that's why your application prints the function itself.
{ title: 'play', random_wordpair: wordpair_controller.wordpair_random}
To fix this, use a callback
exports.wordpair_random = function(callback) {
WordPair.aggregate([$sample: {size: 1}}]).exec(callback);
};
Then in you web function:
router.get('/', function(req, res, next) {
wordpair_controller.wordpair_random(function(err, result) {
//Handle errors if needed.
res.render('play', { title: 'play', random_wordpair:result });
})
});

Send JSON and redirect with Passport authenticate

I'm working with ExpressJS and Passport to authenticate local users, and ideally I want to reply with both a JSON object and a redirect upon success or failure. My code right now looks like this:
app.post('/login', function(req, res, next) {
passport.authenticate('local-signin', function(err, user, info) {
if (err) {
return next(err);
}
if (!user) {
res.json(false);
return res.redirect('/signin');
}
req.logIn(user, function(err) {
if (err) {
return next(err);
}
res.json(user);
return res.redirect('/');
});
})
(req, res, next);
});
The problem is that res.json() and res.redirect() both cause the response to become Finished. Is there some way to have the two happen together? The reason I want to send JSON as well as a redirect is that the login also needs to work from a mobile app, for which redirect doesn't seem to do anything.
If there are better ways to accomplish that, that'd be great too, but the additional info I want to send as JSON would be helpful on the website side too.
Thanks!
EDIT: It looks like I can work with 2 separate routes, however, I'd still like to know if it's possible to both send JSON and redirect.

Asynchronous Request to Facebook API with Redux

I am using Redux and trying to make a call to Facebook API with their JS SDK. I've only ever used promises with Redux and so since the method FB.getLoginStatus just returns a simple JS object, I'm not sure how to ensure that the payload doesn't return undefined.
With redux-promise, you add it to the applyMiddleware(ReduxPromise)... and then it ensures nothing is returned until the promise resolves. But I don't know how to do that here.
I've also used async/await functions with React Native without an issue, but I tried using them here and for some reason the code still returns the payload, before the asynchronous request (await ...) is finished. So I tried working with redux-await, but couldn't get it to work.
export function getLoginStatus() {
var res = FB.getLoginStatus(function(res) {
console.log(res);
});
console.log("res ", res);
return {
type: GET_LOGIN_STATUS,
payload: res
}
}
Hm, things can get a little tricky as I've not used redux-promise. And I can't tell exactly what else you have tried. But this would be my first shot:
async function _getLoginStatus() {
var payload = new Promise( (resolve, fail) => {
FB.getLoginStatus((res)=>resolve(res));
});
return {
type: GET_LOGIN_STATUS,
payload: payload
}
}
// Last time I exported an async function I needed this HYMMV
export let getLoginStatus = _getLoginStatus;
And then elsewhere in the code:
import {getLoginStatus} from 'whatever.js';
var payloadResult = await getLoginStatus();

Backbone.js with MongoDB passing req.params into exports functions

I am trying to send a request parameter through to an 'exports' method for a mongodb find in an express.js, backbone.js application. I am having a difficult
time getting the parameters to pass through to mongodb and with '#'.
The breakage is the passing of parameters into the exported mongodb function.
Here is the flow of data:
First the request is successfully routed to the 'upcoming' function:
"upcoming/uni/:uni" : "upcoming",
It flows on to the 'upcoming' function without a problem.
upcoming: function(uni) {
console.log("uni: "+uni);
pag.reset();
console.log("Hit upcoming list target");
setCollectionType('upcoming');
var upcomingCourses = buildCollection();
// ------------------------------------------------------------------------
// here is the problem how do I pass the parameter value through the fetch?
// Although it may also have to do with '#' please read on.
// ------------------------------------------------------------------------
upcomingCourses.fetch({success: function(){
$("#content").html(new ListView({model: upcomingCourses, page: 1}).el);
}});
this.headerView.selectMenuItem('home-menu');
},
The routing for the mongo methods is:
app.get('/upcoming/uni/:uni', mongomod.findUpcoming);
So the following method is exported from the mongodb js file and is executed reliable. However the req.params are not passed through.
Interspersed in the code I have described its' runtime behaviour:
exports.findUpcoming = function(req, res) {
console.log("university", req.params.uni); // This consistently is unpopulated
var uni = req.params.uni;
console.log("Size: "+req.params.length); // This will always be 0
for (var i=0; i < req.params.length; i++) {
console.log("Parameters: "+req.params[i]);
}
db.collection('upcoming', function(err, collection) {
if (typeof uni === 'undefined') {
console.log("The value is undefined");
uni = "Princeton University"; // here we add a string to test it it will work.
}
collection.find({university:uni}).toArray(function(err, items) {
if (err) {
console.log("Error: "+err);
} else {
console.log("No Error");
console.log("Count: "+items.length);
console.log(items[0]['university']);
res.send(items);
}
});
});
};
On additional and important note:
The url, in a working, runtime environment would be:
http://localhost:3000/#upcoming/uni/Exploratorium
This one fails, but the following URL will work in passing the params through these functions however it returns the JSON to the screen rather then
the rendered version:
http://localhost:3000/upcoming/uni/Exploratorium
The problem could be a miss understanding of # and templates. Please, if you see the error enlightenment would be greatly appreciated.
Nothing after the # gets passed to the server. See How to get hash in a server side language? or https://stackoverflow.com/a/318581/711902.
I found a solution to the problem of passing the parameters from the client side to the server side. By changing the url of the collection the parameters will be passed to the server side:
upcomingCourses.url = "/upcoming/uni/"+uni; // <-- here's the ticket where uni is param
upcomingCourses.fetch({success: function(){
$("#content").html(new ListView({model: upcomingCourses, page: 1}).el);
}});
This can be made more elegant but it is a way to pass the parameters on to the server.
Thanks