# Using a compute and can.batch() to listen to top level state changes

**URL:** <https://forums.bitovi.com/t/using-a-compute-and-can-batch-to-listen-to-top-level-state-changes/834>\
**Category:** CanJS\
**Created:** [March 27, 2018, 2:46pm UTC](https://forums.bitovi.com/t/using-a-compute-and-can-batch-to-listen-to-top-level-state-changes/834 "2018-03-27T14:46:44Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Mike\_Mitchel](https://yyz1.discourse-cdn.com/flex035/user_avatar/forums.bitovi.com/mike_mitchel/32/379_2.png) [@Mike\_Mitchel](https://forums.bitovi.com/u/Mike_Mitchel)\
**Post date:** [March 27, 2018, 2:46pm UTC](https://forums.bitovi.com/t/using-a-compute-and-can-batch-to-listen-to-top-level-state-changes/834/1 "2018-03-27T14:46:44Z")

</div>

Hi All,

I had a performance issue in a CanJS 2.3 app while importing a list of about 200 variables. I assumed it was rendering issue, but when **can.batch.()** did not fix the problem, Justin helped me find the actual issue and fix the code. Lesson I learned here - don’t assume (duh), and always use dev tools to analyze performance to find the cause. More importantly, can.compute with batching let me do something once instead of 2000 times with basic event listeners.

The original app problem and it’s slow solution:  
CanJS changes to the list of variables on a parent `guide` property needed to also update a global, `window.gGuide.vars`, for legacy code in the app to be aware of the CanJS updates. The original solution was using:

```auto
appState.bind('change', (event, attr) => {
    test if the event was for `guide.vars` changing, and if so update `window.gGuide.vars`
}

```

This high level app-state binding on any ‘change’ event firing was generating 1000s of events, each attempting to redraw the entire page, causing the performance issue. Bad news and falls in the ‘should never do’ camp.

The solution still requires the use of can.batch.start() & stop() during the large update to the `guide.vars` Map, but uses a compute at the top level appState which is smart enough to wait for the batch to complete, and only listens for changes on `guide` and `guide.vars`, drastically reducing the number of events:

```auto
var vars = can.compute(function () {
    var vars = appState.attr("guide.vars");
    if (vars) {
      return vars.serialize();
    }
});
vars.bind("change", function (ev, newVars){
    if (newVars) {
      window.gGuide.vars = newVars;
    }
});

```

Hope this helps someone else!  
Mike

P.S. Justin also riffed an idea for a CanJS 4.x solution using `connectedCallback` and `listento`:

```auto
.extend({
    tag: "cali-app",
    ViewModel: {
        get serializedVars(){
            return this.guide?.vars.serialize()
        },
        connectedCallback(el){
            this.listenTo("serializedVars", function(ev, vars){
                can.queues.traceStack()
                window.gVars = vars;
            })
        }
    }
})

```
