Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Computed created each time dirty flag status is checked #30

Open
mdonatas opened this issue Oct 18, 2013 · 2 comments
Open

Computed created each time dirty flag status is checked #30

mdonatas opened this issue Oct 18, 2013 · 2 comments

Comments

@mdonatas
Copy link

If you take this example:
viewModel.dirtyFlag().isDirty();

viewModel.dirtyFlag is a function which creates computed that hashes the model. So each and every single time when you do that viewModel.dirtyFlag().isDirty(); a new computed is created. So after 10 times editing a field you already have 11 computeds doing the hashing. This is a gigantic performance kill.

@mdonatas
Copy link
Author

We ended up with this implementation for our needs. Nice thing about it is that hashing of the model (_objectToTrack) is performed only when it actually changes

; (function (ko) {
    ko.DirtyFlag = function (objectToTrack, isInitiallyDirty, hashFunction) {

        hashFunction = hashFunction || ko.toJSON;

        var
            _objectToTrack = objectToTrack,
            _lastCleanState = ko.observable(hashFunction(_objectToTrack)),
            _isInitiallyDirty = ko.observable(isInitiallyDirty),

            _isDirty = ko.observable(),
            _isDirtyComputed = ko.computed(function () {
                return _isInitiallyDirty() || hashFunction(_objectToTrack) !== _lastCleanState();
            });

        // Set initial _isDirty value
        _isDirty(_isDirtyComputed.peek());

        // Subscribe to computed to update _isDirty observable
        _isDirtyComputed.subscribe(function (value) {
            _isDirty(value);
        });

        // Function for resetting state
        function _reset() {
            _lastCleanState(hashFunction(_objectToTrack));
            _isInitiallyDirty(false);
        };

        var result = function () {
            // Set isDirty to either a simple observable or a computed one depending of whether there is a need to force reevaluation
            // i.g. when the model is made of POJOs
            this.isDirty = function (forceEvaluation) {
                if (forceEvaluation) {
                    return _isDirtyComputed();
                }
                else {
                    return _isDirty();
                }
            };

            this.reset = _reset;

            return this;
        };

        return result;
    };
})(ko);

@jamesarnall
Copy link

It looks like this is a dead thread, but I came here while trying to solve a performance problem, which I ended up fixing by hacking DirtyFlag a bit. When I changed line 63 from

self.isDirty = ko.computed(function () {

to

self.isDirty = ko.pureComputed(function () {

--everything worked just fine. Perhaps someone will find this useful :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants