-
Couldn't load subscription status.
- Fork 958
Description
While reviewing #2256, I considered that maybe a more elegant solution would be to use hold_sync when setting the state from an update message. This would ensure that any new state changes as a direct response to the update (i.e. synchronous changes from validators or observers) all get collapsed into a single update message to the frontend. This collapsed update could then be verified against the property lock simplifying the logic.
A possible problem is that if multiple attributes change, then there is a potential for a change in the order of JS-side change notifications. For example:
- Previously a new state cause the updates:
{foo: 5}, then{bar: 1}. This would trigger thechange:fooandchangeevents on the JS side first, with only foo updated. Thenchange:barandchangewith bar updated. - Now, the new state cause the update:
{foo: 5, bar: 1}. This triggerschange:fooandchange:barin undefined order, then a singlechangeevent, all with both foo and bar updated.
This could potentially be an issue for selections, e.g. here. In this case, the view-code would need to always update the options and index in the same go, using hasChanged to confirm e.g. like this:
initialize(parameters) {
super.initialize(parameters);
this.listenTo(this.model, 'change', (model, value, options) => this._updateSelection(options));
// Create listbox here so that subclasses can modify it before it is populated in render()
this.listbox = document.createElement('select');
}
updateSelection(options: any = {}) {
// Debounce set calls from ourselves:
if (options.updated_view === this) {
return;
}
const optsChanged = this.hasChanged('_options_labels');
const idxChanged = this.hasChanged('index');
// The attributes we care about did not change, skip
if (!idxChanged && !optsChanged) {
return;
}
// Get the index first!
const idx = this.model.get('index');
if (optsChanged) {
// Need to update options:
... // Code as before
}
// Always set the index
this.listbox.selectedIndex = index === null ? -1 : index;
}