I had similar problems in a recent project.
Conceptually, I have a “real” data model (DM) stored on a server, stored in a database.
To bring life to life, the client maintains its own local data model. Outside of client-side DM, all client-side code considers that it outputs results locally.
When reading data (GET) from a DM client, this is:
- checks cache for existing results
- Raises appropriate AJAX requests when cached data is not available, then caches the results.
When changing data (POST) through a client DM, it:
- invalidates the cache file accordingly
- raises relevant AJAX requests
- emits a custom jQuery event indicating a client DM change.
Please note that this client DM also:
- centralizes AJAX error handling
- AJAX tracks are still in flight. (Allows us to warn users by leaving pages with unsaved changes).
- Allows replacement, dummy replacement for unit testing, where all calls fall into local data and are completely synchronous.
Implementation notes:
- I encoded this as a JavaScript class called DataModel. As the project becomes more complex, it makes sense to further divide the responsibilities into separate objects.
- JQuery custom events make it easy to implement an observer pattern. Client components update themselves from the client DM when it indicates that the data has been changed.
- JSON in your remote API helps simplify the code. My client DM stores JSON results directly in the cache.
- The arguments to the client dm function include callbacks, so if necessary, of course, you can pass it through AJAX: function listAll (contactId, cb) {...}
- My project allows only single-user logins. If third parties can change the server data server, you must periodically run some probe with data changes to ensure that the client’s cache is maintained.
- For my application, several client components will request the same data when they receive a client DM change event. This has led to numerous AJAX calls with the same information. I fixed this problem with the getJsonOnce () helper, which manages the callback queue of client components waiting for the same result.
An example function in my implementation:
listAll: function( contactId, cb ) { // pull from cache if ( contactId in this.notesCache ) { cb( this.notesCache[contactId] ); return; } // init queue if needed this.listAllQueue[contactId] = this.listAllQueue[contactId] || []; // pull from server var self = this; dataModelHelpers.getJsonOnce( '/teafile/api/notes.php', {'req': 'listAll', 'contact': contactId}, function(resp) { self.notesCache[contactId] = resp; }, this.listAllQueue[contactId], cb ); }
The getJsonOnce () helper ensures that if multiple client components request the same (unshielded) data, we send only one AJAX request and let everyone know when it arrives.
NotesCache is just a javascript object:
this.notesCache = {};
source share