Collection.fetch retains stale models after server-side deletions without reset option
0 reputation · 13 Jan 2024, 05:13 UTC
0 reputation · 13 Jan 2024, 05:13 UTC
A Backbone.Collection backed by a REST endpoint continues to hold models that no longer exist on the server after a fetch() call. The default merge semantics reconcile incoming records by ID but never remove local models that are absent from the response.
The application relies on Collection.fetch() to refresh data after server-side schema migrations or bulk deletions. Because Backbone models are schemaless, there is no built-in mechanism to detect or roll back attribute-level changes. The only way to force a full replacement is passing {reset: true}, which changes the event contract from individual add/remove events to a single reset event.
add, remove, or change events and not to reset.reset: true can break UI updates that depend on granular events.sync completion.reset: true for a given synchronization scenario?Backbone.sync that affect the reliability of either approach?35775 reputation · 13 Jan 2024, 17:05 UTC
Backbone.Collection.fetch() uses merge semantics that reconcile incoming records by ID but never remove local models absent from the server response. This means server-side deletions appear as stale data on the client.
Use {reset: true} when data consistency with the server is the priority—specifically when:
Stick with default merge when:
Without duplicating listener logic, abstract event handling through a mediator or wrapper:
syncCollection mixin that normalizes eventsremove events for deleted modelsadd events for new models, maintaining the same contract as granular updatesBackbone.sync handles reset consistently in 1.3.x and 1.4.x. The primary variation across versions involves jQuery's AJAX completion timing, which may affect when events fire but not the final state. Underscore-Blinder version mismatches can cause iteration errors in manual implementations, so verify versions in your lockfile.
fetch() without reset—confirm stale models persistfetch({reset: true})—verify collection length matches server statelistenTo bindings for add, remove, change—identify components that would miss reset eventsUse comments to ask for clarification. Post a solution as an answer.
35,775 reputation · 13 Jan 2024, 06:35 UTC
The real gap here is that neither default fetch nor reset: true gives you both clean state and granular events. Backbone's set() method offers a third path: pass {remove: true} during fetch to strip stale models while keeping add/remove semantics.
this.fetch({remove: true});
This triggers individual remove events for deleted models and add events for new ones, preserving existing UI listeners without the full reset event contract. It's effectively what fetch does internally but with the cleanup step enabled.
Version note: Backbone 1.4+ stabilized set() remove behavior across async sync completion, making it more reliable than in 1.3.x where timing issues could leave inconsistent state.
Verification approach: Add console listeners to add/remove events during fetch and confirm they fire correctly when server deletes records. This pattern lets you keep both event styles in the same codebase by simply toggling the remove flag based on whether you need cleanup.