FIRST: I realize this question has been asked here: in ExtJS, is it better to call Model.save() or Store.Sync()? - however I wish to examine this further, specifically regarding minimizing XHR's and unnecessary overhead on both the client and server. I do not feel either of these points were addressed in the linked question.
I have a somewhat large application designed for enterprise resource management, consisting of many models, views and controllers. I handle all responses from my server by establishing a listener to Ext.Ajax requestComplete
and requestException
events. I took this approach rather than writing duplicate event handlers on every model's proxy afterRequest
event. This enables me to have all of my back-end (using the Zend Framework) controllers responding with three parameters: success
, message
and data
.
After a successful request (i.e., HTTP 200), the method run for requestComplete
will inspect the JSON response for the aforementioned parameters. If success
is false
, it is expected that there will be an error message contained in message
, which is then displayed to the user (e.g. 'There was a problem saving that product. Invalid product name'). If success is true, action is taken depending on the type of request, i.e., Create, Read, Update or Destroy. After a successful create
, the new record is added to the appropriate data store, after delete the record is destroyed, and so forth.
I chose to take this approach rather than adding records to a store and calling the store's sync
method in order to minimize XHR's and otherwise round trips. My current means of saving/updating data is to send the request to the backend and react to the result on the Ext front end. I do this by populating a model with data and calling model.save() for create/update requests, or model.destroy() to remove the data.
I found that when adding/updating/removing records from a store, then calling store.sync(), I would have to react to server's response in a way that felt awkward. Take for example, deleting a record:
store.remove()
store.sync()
as I have store's autoSync
set to false
.success: false
, however the record will have already been removed from the ExtJS Data Store.store.sync()
, store.load()
(both requiring a round trip) or get the record from the request and add it back to the store followed by a commitChanges()
to avoid calling an additional sync/load and thus avoiding an unnecessary round trip.The same goes for adding records, if the server fails somewhere while adding data to the database, the record is still in the ExtJS store and must be removed manually to avoid a round trip with store.sync()
or store.load()
.
In order to avoid this whole issue, as I previously explained, I instantiate one of my model objects (e.g. a Product model), populate it with data, and call myModel.save()
. This, in turn, invokes the proxy's create
or update
depending on the ID of the model, and fires the appropriate AJAX request. In the event that the back-end fails, the front-end store is still unchanged. On successful requests (read: success: true
, not HTTP 200), I manually add the record to the store and invoke store.commitChanges(true)
, effectively syncing the store with the database without an additional round trip and avoiding unnecessary overhead. For all requests, the server will respond with the new/modified data as well as a success parameter, and conditionally a message to display on the client.
Am I missing something here, or is this approach a good way to minimize XHR's and server/client overhead? I am happy to provide example code should that be requested, however I feel that this is a rather general concept with fundamental code.
I think you have eloquently argued your position. I don't see anything wrong with the position you have taken. My only reproach is to point out that autoSync setting on a store that backs editable grid is a far less verbose way of accomplishing the task, albeit with less control.
To add, the overhead which you point out is typically due to the unexpected or I would call edge cases that may need special handling or an extra refresh of data. You could add listeners for those specific cases and leave the rest functioning with terse defaults.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With