Skip to content

Commit

Permalink
component.Base: resolveVdomUpdate() => add a smarter way to merge sch…
Browse files Browse the repository at this point in the history
…eduled child updates #6244
  • Loading branch information
tobiu committed Jan 16, 2025
1 parent a5b454c commit 32f7b62
Showing 1 changed file with 38 additions and 22 deletions.
60 changes: 38 additions & 22 deletions src/component/Base.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -402,9 +402,12 @@ class Component extends Base {
}

/**
* @member {String[]} childUpdateCache=[]
* If an update() gets called while a parent is updating, we store the id & distance of the
* requesting component inside the childUpdateCache of the parent, to get resolved once the update is done.
* e.g. childUpdateCache = {'neo-grid-view-1': {distance: 1, resolve: fn}}
* @member {Object} childUpdateCache={}
*/
childUpdateCache = []
childUpdateCache = {}
/**
* Stores the updateDepth while an update is running to enable checks for parent update collisions
* @member {Number|null} currentUpdateDepth=null
Expand Down Expand Up @@ -1954,18 +1957,7 @@ class Component extends Base {
console.warn('vdom parent update conflict with:', parent, 'for:', me)
}

// If our update gets prevented, ensure that the next parent updateDepth
// includes our own updateDepth
if (parent.updateDepth !== -1) {
if (me.updateDepth === -1) {
parent.updateDepth = -1
} else {
// Since updateDepth is 1-based, we need to subtract 1 level
parent.updateDepth = parent.updateDepth + distance + me.updateDepth -1
}
}

NeoArray.add(parent.childUpdateCache, me.id);
parent.childUpdateCache[me.id] = {distance, resolve};

// Adding the resolve fn to its own cache, since the parent will trigger
// a new update() directly on this cmp
Expand Down Expand Up @@ -2346,22 +2338,46 @@ class Component extends Base {
* @protected
*/
resolveVdomUpdate(resolve) {
let me = this;
let me = this,
hasChildUpdateCache = !Neo.isEmpty(me.childUpdateCache),
component;

me.doResolveUpdateCache();

resolve?.();

if (me.needsVdomUpdate) {
// if a new update is scheduled, we can clear the cache => these updates are included
me.childUpdateCache = [];
if (hasChildUpdateCache) {
Object.entries(me.childUpdateCache).forEach(([key, value]) => {
component = Neo.getComponent(key);

// The component might already got destroyed
if (component) {
// Pass callbacks to the resolver cache => getting executed once the following update is done
value.resolve && NeoArray.add(me.resolveUpdateCache, value.resolve);

// Adjust the updateDepth to include the depth of all merged child updates
if (me.updateDepth !== -1) {
if (component.updateDepth === -1) {
me.updateDepth = -1
} else {
// Since updateDepth is 1-based, we need to subtract 1 level
me.updateDepth = me.updateDepth + value.distance + component.updateDepth - 1
}
}
}
});

me.childUpdateCache = {}
}

me.update()
} else if (me.childUpdateCache) {
[...me.childUpdateCache].forEach(id => {
Neo.getComponent(id)?.update();
NeoArray.remove(me.childUpdateCache, id)
})
} else if (hasChildUpdateCache) {
Object.keys(me.childUpdateCache).forEach(key => {
Neo.getComponent(key)?.update()
});

me.childUpdateCache = {}
}
}

Expand Down

0 comments on commit 32f7b62

Please sign in to comment.