I recently started work on an app using a third-party API that deals with posting to and monitoring social networks. Given that the app was going to be a single-page affair and was strictly only going to be using this third-party API, I thought it would be a good chance to dive into some Javascript MVC frameworks.
After a quick survey of my coworkers, all of whom are much more adept at Javascript than I, I decided to try Ember.js and Backbone.js. This blog serves to detail what I was trying to do and how much I failed at progress. While, as of this writing, I have a VanillaJS and jQuery based app that does exactly what I need it to do, I think my failures and roadblocks with Ember.js and Backbone.js might be interesting.
The Goal
Let me set out my goal, so you’ll have some context to understand better why I did what I did and maybe even be able to see me going wrong as it happens.
At work, we have a Django app and I was planning on dropping my Javascript MVC app into a content area with the rest of the page around it generated by the Javascript application.
My primary data source would be the third-party API mentioned above. It’s a pretty straightforward REST API that speaks JSON and does it in a pretty consistent way. I had already written a Python wrapper around the API, so I knew what to expect with my data access methods.
The page as concepted was a one-page app with mostly read views and only one action that would actually need to POST to the API and create new data.
Seemed really simple. I also have a deadline.
The First Problem
Given that Ember.js requires Handlebars.js and Backbone.js works really well with it, I had to figure out how to get my Handlebars templates into a Django template.
I ended up finding this template tag which let me wrap my Handlebars templates so that Django wouldn’t try to evaluate anything inside of the tag.
Problem solved.
My Experience with Ember.js
Like a good programmer should, I first started by reading the documentation for Ember.js. But, like a lot of documentation, it is dense and not terribly good at painting the big picture.
I was excited to find that they had a guides section but frustrated that those guides weren’t exactly of the tutorial type.
Next, I was pointed to this essay by Trek Glowacki as a great resource for how to build an Ember.js app. And that it most certainly is.
However, it’s a step-by-step guide to build a massive app completely in Ember.js. It does not stop to answer questions about how these new concept might or might not match up with concepts with which the reader may be familiar.
That is, it’s a tutorial that requires you to forget everything else you know. This is a great way to truly learn something new, but it’s not so good for productivity under a deadline.
The First Code
With the first code I wrote, I attempted to follow Trek’s guide to the letter. I had outlets and routes and felt good about the structure I was laying out. However, it didn’t really seem to work.
Here’s a look at what the code basically looked like at this point.
The HTML that corresponds to the Javascript in the link above is lost in time. However, the issue was that I was having problems with understanding how the outlets connected to the app and the notion that Trek’s guides seems to assume that the whole page is controlled by the Javascript.
Additionally, I was having issues with how the callbacks that are happening wouldn’t be finished in time for the code that needed to use their results.
You’ll remember the third-part API I talked about. It requires that a signature string be created and appended to every API call.
App.Signature = Ember.Object.extend(); App.Signature.reopenClass({ signature: '', getSignature: function(){ $.ajax({ async: false, url: '/auth/', success: function(response){ this.signature = response; } }); return this.signature; } });
Turns out, I didn’t know anything about promises or deferreds. This was one of the great things I learned when I asked this question on Stack Overflow. This is clearly not an Ember problem, but it was something great to learn.
I quickly realized that the outlets and routes wouldn’t work for me, mostly because it seemed like my simple app didn’t need them. They were just clouding my already muddled understanding of what I was doing.
The Second Code
Through some trials and tribulations, I eventually was able to cobble together some code that sort of worked. It seemed like I had a lot of verbose code that didn’t do much except to get things set up.
As a heavy jQuery user, I kept thinking to myself that the functionality I had could essentially be done in about half the code if I just used jQuery. Sure, it might not have the structure I was searching for, but the question still nagged.
This is the code as it stood and was sort of working.
The error that I had with this code was that The PostedPiblications data was always one action behind the PostedPubsCampaign selection. That is, if the app loaded with the data for campaign A, then the user changed the selection to campaign B, nothing would happen. I the user then selected campaign C, the PostedPublications shown on the page would belong to campaign B.
I could see that the correct API call was being made, but the page wasn’t updating as expected. After fighting for this for a full day, I posted this StackOverflow question that remains unanswered with 40 views.
Despite the fact that I had some code that worked moderately well, I still didn’t really understand why I needed controllers and views. The models didn’t seem to quite work the way my conception of models does (based on my experiences with Django and Sqlalchemy models).
Getting Help
You’ll notice that I posted a few question on StackOverflow while working through this Ember.js work. I was also in the #emberjs IRC channel often and asking questions in there. Adding to that numerous Google searches and bugging my coworkers and I was quickly exhausting my supply of resources.
Given the relative newness of Ember.js and the current lack of experienced folks who have built apps with it AND are willing to help in IRC, blog, answer SO questions, etc., it’s a challenging environment for a newbie. I did just stumble on EmberNoob and that may grow into a nice resource.
All of this trouble left me frustrated, confused and still staring at a looming deadline.
Trying out Backbone.js
At this point, one of my coworkers made the point that we were already using Backbone.js in many other places in our application. Now that I had a good sense of what I wanted to do in the app, it might be easier to learn Backbone instead of Ember.
I took essentially a day and ported the code I had over the Backbone.js and ended up with this bit of code.
With this, I couldn’t get past the point of a syntax error. JSLint wasn’t helping and no one in the office could figure it out. It was at this point, with 4 days of Ember experimentation and 1 day of Backbone coding, that my deadline pressure started tickling the back of my brain and I had to move on to technologies I already knew.
Temporary Conclusion
The tenor of this post might lead you to believe that I don’t like these two projects and think they aren’t valuable. Quite the contrary.
Both of these Javascript MVC frameworks have great promise for me and I intend to find another, perhaps better, situation in which I can learn and use them. I really appreciate the structure and modularity that both projects brought to my code.
I also appreciate that they forced me to think about my Javascript code in ways I previously hadn’t had to. I like the idea of having the code that gets the data into the DOM be somewhat transparent to the code that pulls that data from its source.
I’ll come back around to both Ember.js and Backbone.js again.
Learnings
In the course of this work, I learned a good deal about promises and deferreds. Additionally, I was exposed to the beauty that is Underscore.js and Moment.js. That progress alone was worth delving into this stuff.
Comments !