mardi 21 avril 2015

Ember.js how to execute code asynchronously

I have some ember.js code that authenticates users by twitter and google. I have a navbar with a link to my login page that i want to change to a link to my users profile after they authenticate. How do i get the authentication data before my code tries to change the link.

I am guessing that i need to rewrite login in my session initializer to become a promise and then rewrite my login controller to utilize the new promise.

So i have read about Ember.RSVP.Promise here and here and tinkered around trying to get it to work but to no avail.

Below is my code for my session initializer and for my login controller

import Ember from 'ember';

export default Ember.ArrayController.extend({
        needs:['application'],

    actions:{
        loginTwitter:function(provider){
            this.get('session').login(provider).then(function(authData){
                this.set("controllers.application.registered",true);
                console.log(authData);
                var user = authData.twitter.displayName;
                this.set("controllers.application.user",user);
            });
            // var authData = this.get('session').authData;
            // if(authData){
            //  this.set("controllers.application.registered",true);
            //  console.log(authData);
            //  var user = authData.twitter.displayName;
            //  this.set("controllers.application.user",user);
            // }
            this.transitionToRoute('index');
        },
        loginGoogle:function(provider){
            this.get('session').login(provider).then(function(authData){
                this.set("controllers.application.registered",true);
                console.log(authData);
                var user = authData.google.displayName;
                this.set("controllers.application.user",user);
            });
            // var authData = this.get('session').authData;
            // if(authData){
            //  this.set("controllers.application.registered",true);
            //  console.log(authData);
            //  var user = authData.google.displayName;
            //  this.set("controllers.application.user",user);
            // }
            this.transitionToRoute('index');
        },
        underConstruction:function(){
            alert("Sorry this feature is under construction");
        }
    }
});

session initializer

/*
 * Working authentication with
 * Firebase 2.0.x + Ember.js 1.8.1 + Ember Data Canary + EmberFire 1.3.0 + Ember CLI
 * works for me! oskar@rough.dk
 *
 * Note: this assumes you've set up login on your Firebase,
 * only handles Google and Facebook for now,
 * 
 * In your templates: <button {{action 'login' 'google'}}>Log in with Google</button>
 */


/*global md5*/
import Ember from 'ember';

// Since I've defined my url in environment.js I can do this
import ENV from '../config/environment';
var ref = new window.Firebase(ENV.firebase);

export default {
    name: 'session',

    // Run the initializer after the store is ready
    after: 'store',

    initialize: function(container, app) {  
        // session object is nested here as we need access to the container to get the store
        var session = Ember.Object.extend({

            // initial state
            authed: false,

            init: function() {

                // get access to the ember data store
                this.store = container.lookup('store:main');
                // on init try to login
                ref.onAuth(function(authData) {

                    // Not authenticated
                    if (!authData) {
                        this.set('authed', false);
                        this.set('authData', null);
                        this.set('user', null);
                        return false;
                    }

                    // Authenticated
                    this.set('authed', true);
                    this.set('authData', authData);
                    this.afterAuthentication(authData.uid);
                }.bind(this));
            },

            // Call this from your Ember templates
//I think this is the function i need to turn into a promise

            login: function(provider) {
                this._loginWithPopup(provider);
            },

            promise:function(){
                new Ember.RSVP.Promise(function(resolve,reject){
                var loggedIn = this.login();
                if(this.get('authed')){
                    resolve(loggedIn);
                }else{
                    reject(loggedIn);
                }
            });
            },

            // Call this from your Ember templates
            logout: function() {
                ref.unauth();
            },

            // Default login method
            _loginWithPopup: function(provider) {
                var _this = this;
                // Ember.debug('logging in with popup');
                ref.authWithOAuthPopup(provider, function(error, authData) {
                    if (error) {
                        if (error.code === "TRANSPORT_UNAVAILABLE") {
                            // fall-back to browser redirects, and pick up the session
                            // automatically when we come back to the origin page
                            _this._loginWithRedirect(provider);
                        }
                    } else if (authData) {
                        // we're good!
                        // this will automatically call the on ref.onAuth method inside init()
                    }
                });
            },

            // Alternative login with redirect (needed for Chrome on iOS)
            _loginWithRedirect: function(provider) {
                ref.authWithOAuthRedirect(provider, function(error, authData) {
                    if (error) {

                    } else if (authData) {
                        // we're good!
                        // this will automatically call the on ref.onAuth method inside init()
                    }
                });
            },

            // Runs after authentication
            // It either sets a new or already exisiting user
            afterAuthentication: function(userId) {
                var _this = this;

                // See if the user exists using native Firebase because of EmberFire problem with "id already in use"
                ref.child('users').child(userId).once('value', function(snapshot) {
                    var exists = (snapshot.val() !== null);
                    userExistsCallback(userId, exists);
                });

                // Do the right thing depending on whether the user exists
                function userExistsCallback(userId, exists) {
                    if (exists) {
                        _this.existingUser(userId);
                    } else {
                        _this.createUser(userId);
                    }
                }
            },

            // Existing user
            existingUser: function(userId) {
                var _this = this;
                this.store.find('user', userId).then(function(user) {
                    _this.set('user', user);
                }.bind(this));
            },

            // Create a new user
            createUser: function(userId) {
                var _this = this;

                this.get('store').createRecord('user', {
                    id: userId,
                    provider: this.get('authData.provider'),
                    name: this.get('authData.twitter.displayName') || this.get('authData.google.displayName'),
                    email: this.get('authData.facebook.email') || this.get('authData.google.email'),
                    created: new Date().getTime()
                }).save().then(function(user){

                    // Proceed with the newly create user
                    _this.set('user', user);
                });
            },

            // This is the last step in a successful authentication
            // Set the user (either new or existing)
            afterUser: function(user) { 
                this.set('user', user);
                return this.authData;
            }
        });

        // Register and inject the 'session' initializer into all controllers and routes
        app.register('session:main', session);
        app.inject('route', 'session', 'session:main');
        app.inject('controller', 'session', 'session:main');
    }
};




Aucun commentaire:

Enregistrer un commentaire