The Story So Far
In the last post, I set up a Backbone view and a model, and connected the two. I also connected the view to a route so that we could see it render with the data. This time I want to figure out:- How to query the Facebook Graph API
- How to persist data to the Parse backend
The Graph API
The first thing you will need to hit the Graph API is an access token. This token as an associated set of permissions which will determine which of your queries succeed. When you play with the Graph API Explorer, you will see a button saying "Get Access Token", which brings up a window asking you which permissions you are going to ask the Facebook user for:
When you do this through Parse, you will ask for permissions in the call to Parse.FacebookUtils.logIn. If the user grants you the permission you want, the access token will be in Parse.User.current()._serverData.authData.facebook.access_token.
To use this token to make a query, you call the FB.api function. Which works fine... except when the FB object doesn't exist yet. Or the Parse.User hasn't signed in. Or the access token has expired. All of which are possible, especially if the initialization flow is still in progress.
To handle this I wrote a little helper:
facebookQuery = function(queryString, callback) {
var doer = function () {
if ((!!window.FB) && (!!Parse.applicationId) && (!!Parse.User.current())) {
window.FB.api(queryString, { 'access_token': Parse.User.current()._serverData.authData.facebook.access_token }, function(response) {
// token expired! this logic needs to be a)understood, and b)put everywhere
if(response.hasOwnProperty('error') && response.error.code === 190) {
Parse.User.logOut();
Invite.loginUser(doer);
}
else {
callback(response);
}
});
}
else {
// wait 0.1s
setTimeout(doer, 100);
}
};
doer();
};
The 190 error code is what Facebook returns if the access token has expired. What I do is I log out and log back in, and this seems to work.
Persisting to Parse
They have actually made this pretty easy - the Parse.User object has a save method you can call. Here is some code which shows a Graph query for the logged-in user's profile information - you can see that I am asking for only the name, gender, and cover photo. Then I call the set method to assign to the fields, followed by save to send it to their servers. facebookQuery('/me?fields=name,cover,gender', function(response) {
// information to populate the model
var info = {
fbId : response.id,
realname : response.name,
gender : response.gender,
privacy_non_fb_see_only_name : Parse.User.current().get("privacy_non_fb_see_only_name"),
photoURL : response.cover && response.cover.source
};
// overwrite existing values, if any, and send to Parse
_.each(info, function(val, key) {
Parse.User.current().set(key, val);
});
Parse.User.current().save();
//
next(info);
});
