Search code examples
javascriptbackbone.js

backbone js - reduce calls to the server


Just wondering how people deal stopping multiple external server calls? I'm doing everything in the .complete of the fetch because otherwise when I try to call anything the fetch hasn't completed and nothing is populated in the collection.

I'm new to backbone so I'm probably missing a trick.. but is there a way to do a fetch and store that information somewhere so that you never have to fetch again, you just work off the collection as a variable? All of my information comes from an external site, so I don't want to be making lots of unnecessary external calls if I can. I'm not updating the server or anything, its all just read-only.

What do other people do for a similar set up? Am I missing something silly? Or am I set up badly for this? Here's what I have so far (work in progress)

Oh also: I'm doing the fetch in the router.. is that a bad idea?

http://jsfiddle.net/leapin_leprechaun/b8y6L0rf/

.complete(
    //after the fetch has been completed
    function(){
        //create the initial buttons
        //pull the unique leagues out
        var uniqueLeagues = _.uniq(matches.pluck("league"));

        //pull the unique leagues out   
        var uniqueDates = _.uniq(matches.pluck("matchDate"));

        //pass to info to the relative functions to create buttons   
        getLeagues(uniqueLeagues);
        getMatchDates(uniqueDates);
        homeBtn();
        fetched = true;
    }
); //end complete

Thanks for your time!


Solution

  • This is an often recurring question but the answer is rather simple.
    Perhaps I'll make some drawings today, if it helps.
    I never took the time to learn UML properly, so forgive me for that.

    1. The problem

    What you currently have is this:

    enter image description here

    The problem however is that this isn't very dynamic.
    If these 3 functions at the right would require to be executed from different ajax callback functions, they need to be added to any of these callbacks.
    Imagine that you want to change the name of any of these 3 functions, it means that your code would break instantly, and you would need to update each of these callbacks.

    Your question indicates that you feel that you want to avoid every function to perform the async call separately, which is indeed the case because this creates unnecessary overhead.

    2. Event aggregation

    The solutions is to implement an event driven approach, which works like this:

    enter image description here

    This pattern is also called pub/sub (or observer pattern) because there are objects that publish events (in this case on the left) and objects that subscribe (on the right).
    With this pattern, you don't need to call every function explicitly after the ajax callback is finished; rather, the objects subscribe to certain events, and execute methods when the event gets triggered. This way you are always certain that the methods will be executed.
    Note that when triggering an event, parameters can be passed as well, which allows you to access the collection from the subscribing objects.

    3. Backbone implementation

    Backbone promotes an event driven approach.
    Setting up an event aggregator is simple and can be done as follows:

    window.APP = {};
    APP.vent = _.extend({}, Backbone.Events);
    

    From the ajax callback, you just trigger an event (you give it any name you want, but by convention, a semi colon is used as a separator):

    APP.vent.trigger("some:event", collection);  
    

    The three receiving objects subscribe to the event as follows:

    APP.vent.on("some:event", function(collection){ 
        console.log(collection.toJSON()); 
    }); 
    

    And that's basically all.
    One thing to take into account is to make sure that when you subscribe to events using "on", you also need to un-subscribe by calling "off", if you no longer need the object.