Reflow thrashing, reflow throttling, etc.

I've run into a scenario that triggers enyo to execute the same reflow method many times in a short timeframe and I was wondering if anyone has run into this before and figured out some ways to deal with this.

Consider the following simplified example scenario:
enyo.kind({
    name: "myDocument",
    model: new MyModel(),
    components: [{
        name: "myTitle",
        content: ""
    }, {
        name: "body",
        content: ""
    }],
    bindings: [{
        from: ".model.title",
        to: ".title"
    }, {
        from: ".model.subtitle",
        to: ".subtitle"
    }, {
        from: ".model.body",
        to: ".$body.content"
    }],
    computed: {
        compositeTitle: [
            "title",
            "subtitle", {
                cached: true
            }
        ]
    },
    compositeTitle: function() {
        var title = this.get("title") || "",
            subtitle = this.get("subtitle") || "";

        return [title, subtitle].join(" ").trim();
    },
    compositeTitleChanged: function() {
        this.$.title.set("content", this.get("compositeTitle"));
        this.owner.resized();
    }
});
This kind binds to updates from it's model, computes a compositeTitle out of multiple values and updates the content of myTitle with the resulting compositeTitle.

Lets say the owner of this kind has a custom layout that depends on the height of the rendered myTitle component. Now any time the myDocument updates it's title content, the height of the title might change. So, upon every update, we tell the owner it's resized so it can reflow and take into account the new title's height.

If the model updates, it might have both a new title, and a new subtitle, causing the compositeTitle be recalculated twice (once for each updated binding), leading to two reflows on the owner where a single one at the end would have been sufficient.

Two reflows isn't necessarily *that* bad, but the problem can easily grow a lot worse if the entire model instance get's replaced, or if the compositTitle would be composed out of more components, or components originating from multiple datasources, etc.

Some tried solutions that aren't good enough
- One option would be to construct some specialized logic to determine if enough changes have happened to justify resizing the owner. But this could easily get complicated and messy.

- You could try debouncing the reflow method, but this breaks the resize flow, because the resize event expects a synchronous reflow rather than an asynchronous reflow.

- You could try debouncing the resized method, but that would create extra delays for each debounced resized method in the component hierarchy.

- You could try debouncing the resizeHandler method, but that would create a similar problem as the debounced reflow method.

It seems throttling or deferring flow-related methods just doesn't work well because of it's inherently synchronous design and wreaks havoc on content flows that require multiple reflow passes.

Even better would be to simply throttle the computed method, but this resulted in incomplete computed values getting cached when I tried it and altering the behaviour of part of enyo's kernel seems like an exceedingly dangerous route to take.

So, I was wondering if anyone has done any work towards handling multiple reflow calls in short succession.
Sign In or Register to comment.