feat(runtime-core): export queuePostFlushCb #1078
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
In some cases (such as the Vugel renderer), action needs to be taken immediately after a patch. nextTick could be used. But the danger is that application callbacks could be scheduled before it. queuePostFlushCb allows us to implement a more 'integrated' and less error-prone mechanism.
Our use case
In the case of Vugel, we use Vue3 with the custom renderer api to render on tree2d nodes. Three2d uses a render tree with children stored in arrays rather than linked list (HTML DOM). This causes O(n*n) complexity when adding new elements to a v-for. It leads to bad performance in some cases, when using a lot of items in a v-for. This is caused by the facts that vue iterates all items from the start, and when inserting new items one by one at the start of the array it will have to be copied over and over. We had a (very heavy, 10'000 item) case where an update took 1 second.
After our fix it went down to 60ms. We deferred the synchronisation between Vugel and tree2d until after all child operations (per parent node) have been done. One problem we had is that we can't tell which operation (appendChild, insertBefore, removeChild, clearChildren) operation is the final one. So we wait until a new parent is encountered (vue patches the list items until traversing into the children).
This allows us to sync all nodes properly except for the last encountered one. Because we have no way of telling when the complete patch was done. For this reason, we sync the last encountered parent using
nextTick()
. https://github.com/Planning-nl/vugel/blob/master/src/runtime/nodes/Base.ts#L132But the danger is that application callbacks could be scheduled before it.
queuePostFlushCb
allows us to implement a more 'integrated' and less error-prone mechanism.