mbuchetics
mbuchetics

Reputation: 1410

Order of events triggerd by Backbone.Router when using navigate

I am using Backbone's "all" event to catch all route events in my app in order to log the page views. This works well as long as I don't use navigate to manually trigger a route. In the following example, I forward the user from the dashboard route to the login route. Backbone fires the event AFTER the route callback is executed, leading to the following output:

showDashboard
showLogin
route:showLogin
tracking:/login
route:showDashboard
tracking:/login

Obviously this is not what I want. I know I could call showLogin instead of using navigate to trigger the login route and this is what I am doing right now, but I would like to know why the order of the events is not the same than the order of the triggered callbacks.

Here is my router (shortened):

var AppRouter = Backbone.Router.extend({
    routes: {
        "/login": "showLogin",
        "": "showDashboard",
    },
    initialize: function() {
        return this.on('all', this.trackPageview);
    },
    trackPageview: function(eventName) {
        console.log(eventName);
        var url = Backbone.history.getFragment();
        console.log('tracking: ' + url);
    },
    showDashboard: function() { 
        console.log('showDashboard');
        // check if the user is logged in etc.
        this.navigate('#/login', { trigger: true });
    },
    showLogin: function() {
        console.log('showLogin');
    }
});

Upvotes: 0

Views: 1476

Answers (1)

rfunduk
rfunduk

Reputation: 30442

Backbone's Router is actually very simple, and if you read the code you'll see the following in it's constructor:

this._bindRoutes();
this.initialize.apply(this, arguments);

_bindRoutes attaches all your routes as you expect, and it does this before your initialize function gets called. So your binding will always fire after Backbone's does.

You're probably going to be better off finding another way to do this.

You could call a before type function yourself in your routes to do stuff like track pageviews/etc. Or maybe you could just override route, track your pageview and then make sure to call Backbone's implementation with something like Backbone.Router.prototype.route.call(arguments);

Upvotes: 1

Related Questions