Hey Patrick - there are a couple of important questions you bring up in this
thread, i'll do a quick brain dump and then let's follow up and try to tease
them all out into the right patterns/reasons.
blog/blob/master/js/views/root.js would allow caching of the application states
- basically this seems extraneous when first seeing the output of the generator,
but as soon as you make two routes, each with their own layout view(or perhaps
collection-view in the case of a /posts), navigating back and forth between the
routes is more performant when you don't have to recreate the views (and their
model/collection objects) each time (navigating to home, then posts, then home,
then posts would only instantiate home and posts one time each, instead of 2
times each -- this is a huge performance win, especially on mobile networks...
this naturally leads to the next question, where do i load my data the first
time and/or update an instance of a collection with new data(which would then be
available throughout app)... this is a really interesting important question..
loading -- which i've begun doing. also embedded in this question is, during
development, how do i mock my data and test loading/success states(which have
their own views)... im a bit lazy today, the following are notes i took while
looking into answering this today(at random times), i should refactor but i
paste in haste, forgive me, we'll hash this out in time though, (aka, rough
draft notes ahead)
this naturally leads to the next question, where do i load my data. this is a
really interesting and important question.. developer happiness,
performance(especially on mobile networks), async requests in parallel,
errors from the server and the ability to test it all converge here...
just briefly, there seem to be some common ways of managing reponses from the server during
development: (you these too, just writing for sake of completeness, please add your thoughts too)
- use a real server - this is not ideal b/c instead of worrying about the response
your app needs, you now need to worry about the server side stuff, slowing you down
and making iteration of the app slow.
- use fixture data - throw some json into an object or even a file and override
the fetch method, or $.ajax to return this data until you get the real deal
api in place. the problem here is that a) you need to make sure the data is returned
from fixtures async, thus you might as well use a real server - which is slightly
better, but discussed already(above)
- use something like sinon fake server -- this works for one off stuff, and is
a bit better than just returning data from an object -- sinon can be setup to
return data async by using respondWith, then make the call, then use server.respond.
honestly though, this only works well for serving all 200 responses, once you
becomes a nightmare to manage. loading/success (and ideally) failure states are
important for SPA apps - loading helps with mobile latency, every app should
show a good page when requests fail(and do a back off too try again first) -- but to do
this in sinon you would need to stub the clock + use a sinon server, at which
point you might use sinon sandboxes, which then break mocha's async testing
ability and eventually you'll end up with what has happened within the thorax
source code, inside test/src/loading.js -- in general the environment takeover
that sinon does sucks, i hate it, only use sinon for spying on callbacks IMHO,
even then, a simple counter will work with less weight(end rant)
- the last option is to listen for the loading:start and loading:stop events and
return different data for each.. a loading:error state could also be handled too...
on top of this, my distant dream is to instead use promises, something like
visit('/posts').
.then(function(loadingData) {
// test the loading state with loading data, in reality, there prob isn't
// any loading data, so arg is prob optional
})
.httpRespond("get", "/api/articles", [{id: 1, body: '...'}, {id: 2, body: '...'}])
.then(function(successData) {
// the happy path, test the success state with all the data
})
.click('some buttong')
.fillin('some data')
.httpRespond("post", "/api/articles/1/comments", {id: 1, body: comment})
.then(function(loadingData) {
// test loading state, which uses data sent to server, will likely be same
// as success, unless error comes back, in which case success migh have
// little banner flag drop down saying your offline, etc
})
.then(function(successData) {
// my fingers are tired, you prob get the point by now
})
.catch(function(failureData) {
// handle failure with a faiure state
})
something like the above can be implemented on top of thorax currently by overriding
collection/model fetch methods, simply wrapping them in a promise prototype that has
been extended with an event emitter mixin (rsvp has this feature) -- i need to
write up an example for this, perhaps the day after xmas -- at which point
i should start having more time to play around again(been travelling so tough, but
will be staying put soon on 26th - 6th, in which i'd like to hash some of these ideas
out further and see if there is anything here (ember does something like this, actually thorax
has the primitives, the promises would make the api nicer... also might help with the
singleton pattern thing -- )
note that in a way this also an argument for promises A+ support on top of the
event loading/backbone.fetch event/jquery stuff... it wasn't intended to be, but the
third option of testing/mocking data w/ loading view support is not possible this cleanly
unless promises chaining is supported, which i think jquery botches, although maybe im wrong on that,
i do know errors won't bubble without a real promise lib under the hood.. thats a whole other topic
though, for later...
any more right now on this topic will have to wait, beer has just arrived, but i am
interested in finding a good solution, even just to explore the problem further and
learn, for fun as they say. first i think starting with just the load:start and load:end
events and responding to with fake data for the load:start event would be a good way
this is totally a discussion by the way, and I totally took some of this from
my experience working with ember, which has test helpers like this and promises
throughout... the data story there originally comes from research by mark miller
who's thesis was on distributed systems in a language called e, which supported
async message sends between isolated environments running concurrently
but communicating via events quees - which later informed google's caja project, which
became web workers/secure iframes/ and now navigation controller, all stuff that is new web api
specs held, which all work via events but abstract out to work well togethter
by promise chains which just became a standard in es6 -- and which would ideally
become popular in browser libraries and someday in node -- perhaps node will just use
es6 generators w/ streams instead, like the new koa library that i aims to replace expressjs...
anyway the point being that loading data/handling errors/communicating across networks
in a single threaded language like javascript naturally abstracts into the promise
pattern that has roots, aka, i didn't just make it up(over this beer)...
im totally off topic, but perhaps you may want to grab bag some of this stuff for
your book, so i brain dump away
by the way another good example to try this with would be talking to more than one api at once from within
an app, even if you have to use a proxy to get passed cors headers... the result of such
an experiment i have in progress as well, if your interested...
k, cold beer me
lets chat again after xmas and hash this out into something more coherent. the
tl;dr is that data loading on the client is a big topic, but one that has good
answers we shall explore in more detail