You're on the right track, I would say, but save your data in JavaScript first. And connect it to the local store when it comes up.
When I create applications such as the one you are describing, I usually try to tweak the JavaScript views for the data retrieved through the API.
One of such representations may look as follows. Keep in mind that the following code example makes a few assumptions.
- It is assumed that you have a specific
api
object that is responsible for API calls and calls a callback at completion. - that the data returned by the API is JSON, which can simply be assigned to a JavaScript variable,
- The JSON return is a list of objects, each of which has an id field.
- That you have some kind of event object, I usually create my own custom events that basically carry
function
objects as listeners, and when they are launched through listeners and call functions with or without payload, depending on the situation.
Example data container:
MYAPP.data.BaseContainer = function (api_url, loadedEvent) { var self = { // Array to store the data returned via the APIs _data : [], // The API URL used to fetch data api_url : api_url, // Boolean flag to signify whether the _data variable has been populated is_loaded : false, // The even to fire once _data has been populated loadedEvent : loadedEvent, /** * Returns the state of the is_loaded variable */ loaded : function () { return self.is_loaded; }, /** * Takes an ID and returns any member of the _data array * that has that ID. * * @param id : an String or integer representing the ID. * @returns {Object} */ byId : function (id) { var toReturn = null; for (var i = 0, len = self._data.length; i < len; i++) { if (self._data[i].id == id) { toReturn = self._data[i]; break; } } return toReturn; }, /** * Returns the entire _data array. */ all : function () { return self._data; }, /** * This simple callback just stores the json response in * its entirety on the _data variable. */ callback : function(data) { self._data = data; self.is_loaded = true; loadedEvent.fire(self._data); }, /** * Calls the API, if no callback has been specified as a parameter * self.callback is used. */ getFromAPI : function(callback) { if (typeof callback === 'undefined') { callback = self.callback; } api.get(self.api_url, callback); } }; self.getFromAPI(); return self; };
With this drawing, I can now create specific data containers as follows:
MYAPP.data.Friends = (function () { var self = MYAPP.data.BaseContainer("API_URL_TO_FECTH_FRIENDS_LIST", FriendsLoadedEvent); return { byId : self.byId, all : self.all, loaded : self.loaded }; }());
Once this code is run, an API call is made and FriendsLoadedEvent
will be launched when it is done. Therefore, to be honest, I usually use JavaScript to store my stuff. But if you want to throw LocalStorage into the mix, it's easy too!
Just add the local storage code to the BaseContainer object, which first determines whether the client really supports localstorage, and if it is a mirror of the _data field in local storage. This is convenient for quick access to frequently used data between sessions. Use the easily accessible JSON parsing tools to convert data from JSON to "Text" and back to "LocalStorage".
Just keep in mind that you cannot rely on LocalStorage as your main data structure, you have no guarantee that the client supports it, and even when it meets the upper bound on how much data you can actually store, it differs between browsers, therefore use it to store data that:
- You want to access very often,
- which, in your opinion, should just be there, as soon as the user logs in,
- and it does not change often enough to constantly update API calls.