mbest / knockout-deferred-updates

Deferred Updates plugin for Knockout <=3.3.0
http://mbest.github.io/knockout-deferred-updates/
134 stars 23 forks source link

Browser CPU goes to 100% after including this js on my page #18

Closed paulrosen closed 10 years ago

paulrosen commented 10 years ago

I have a number of console messages, and it looks like it does a bit of initialization, then pauses (maybe for garbage collection?) then does more initialization. I can't tell, but it looks like it is looping on the same initialization over and over.

I'm using KO 3.0, I saw this on chrome, and it is during page load, where I'm loading all my stored data into the ko observables.

I'm not sure what other info is useful to you, but I'll expand this description however you like.

Thanks!

mbest commented 10 years ago

Can you try with the latest development version: https://raw.github.com/mbest/knockout-deferred-updates/master/knockout-deferred-updates.js

paulrosen commented 10 years ago

I did, and it didn't seem to help. I did notice this time that it appears to be changing some observables through the UI, which is triggering ajax updates and probably causing a loop during initialization.

(I don't doubt it is a problem with my architecture, but I have no idea what I've set up wrong. My symptoms before trying your library are slow initialization, and repeated and unnecessary calls to ko.computed functions.)

My general architecture is that I've got an array of parent objects that have some observables and some computeds. Then each one of those has a array of child objects that also have some observables and some computeds. There is also a "current parent object" that is put on the page, and a "current child object" that is also on the page.

So, when the user switches to a different child object, then 30 or so observables are set into the "current child object". I'd love to just turn off ko, set those values, then turn it back on so I just get one update. But your library seems like it should do the trick, too.

Anyway, thanks for the rapid response!

mbest commented 10 years ago

It's likely that you have some sort of recursive dependency within your computed observables.

mbest commented 10 years ago

Maybe the discussion in #17 can help.

paulrosen commented 10 years ago

I did read that issue before posting! I promise!

I'll try to figure out if I have a recursive dependency, but I'm not sure how to track that down. Thanks for your help!

mbest commented 10 years ago

Since you're interested only in speeding up a specific part of your code, you can try turning off deferred updates in general and only turning it on for the specific part of your code that needs it.

After including knockout-deferred-updates.js:

<script>ko.computed.deferUpdates = false;</script>

Then in your code that needs to delay updates:

ko.computed.deferUpdates = true;

// update a bunch of observables

ko.processAllDeferredUpdates();
ko.computed.deferUpdates = false;
paulrosen commented 10 years ago

I tried putting ko.computed.deferUpdates = false; in, but the browser still locks up on load. I put it in a couple places: in the script tag you suggested, and also at the top of js file that is loaded after yours.

I don't know if this matters, but I'm using the debug version of ko. The first line in the file is:

// Knockout JavaScript library v3.0.0

I'm also loading in knockout.validation.js and knockout.bindings.dataTables.js, and I'm running jQuery.

mbest commented 10 years ago

Can you try it with an earlier version of Deferred Updates? https://rawgithub.com/mbest/knockout-deferred-updates/acb19c5cbe47134e2c45943a0a5060a5e714b9de/knockout-deferred-updates.js

paulrosen commented 10 years ago

That version, along with setting deferUpdates to false, allows my page to load -- so that gets me a little farther.

Without the deferUpdates line I still get the infinite loop.

Do you know of any way to find a circular ko reference? I think I might need to comment out most of my program and slowly add functions back until it fails. That might take a while.

mbest commented 10 years ago

Without Deferred Updates included, add a breakpoint in knockout-3.0.0.debug.js on line 1438. This will break whenever a computed observable is updated recursively. Some of these will be innocuous (they won't cause the infinite recursion), but obviously at least one is the culprit.

paulrosen commented 10 years ago

Thanks for the tip! That did give me a clue. I'll fix that, then try the newest version of this library again. I'll let you know if anything else goes wrong.

Thanks a lot for your time.

mbest commented 10 years ago

Can you share what you found? Thanks.

paulrosen commented 10 years ago

Well, I didn't get back to using your library. What I did was replace all the computed() items with my own method that has two changes:

1) The recalculation is called explicitly, so I can just decide when I am finished changing things. 2) I pass in the set of dependencies when first setting up the item, so I can easily see and change why a function is called.

So, I created a function on my model that looks like this:

calculated('variableName', [ 'dependency1', 'dependency2' ], function() { ... });

And that turns the variableName into an observable() that I set in a function called recalculate().

mbest commented 10 years ago

Sounds like a great approach.