1

Hi i have read the documentation and a couple of blog posts and i still don't understand what is happening with .bind(this) in the code below.

The code works for me but i hate not understanding what is going on

  1. What would happen if i deleted .bind(this) from the code below?
  2. What is getting bound to what?

    

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
            login: function(provider) {
                this._loginWithPopup(provider);
            },

            // 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.facebook.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);
            }
        });

        // 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');
    }
}; <code>
rog
  • 5,351
  • 5
  • 33
  • 40
tharderer
  • 83
  • 1
  • 5

1 Answers1

2

You are using .bind(this) on a callback function. That means, that the this inside the function would normally refer to the context where the function is called (this is JavaScript, which is different from other languages regarding contexts). You want this to refer to the current context. And that's just what .bind(this) does: It ensures that the callback function will be called with the current context (instead of its default context).

jnfingerle
  • 713
  • 4
  • 16
  • Ha! so thats just a basic lack of javascript understanding on my part and nothing to do with ember.js no wonder i couldn't find any documentation:)Thanks! – tharderer Apr 07 '15 at 22:56
  • 1
    It's standard JS: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind – jnfingerle Apr 07 '15 at 22:58
  • On a side note there is an `Ember.run.bind` that's used to add third party listeners/functions to the run loop. – Patsy Issa Apr 08 '15 at 10:24