1
votes

Recently I bumped on rather weird code in the project I'm currently working on. Here is the isolated example depicting the issue:

<html lang="en-US">
<head>
  <meta charset="UTF-8">
</head>
<body>
    <input type="text" data-bind = "value: firstName">
    <input type="text" data-bind = "value: lastName">
  <br />  <br />
  <span data-bind = "text: firstName"></span>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
  <script>
    var myViewModelProto = function(){
    self = this;
    this.firstName = ko.observable("John");
    this.lastName = ko.observable("Smith");

    ko.computed(function(){
        alert(self.lastName());
    });
};

var vm = new myViewModelProto();
ko.applyBindings(vm);
</script>
</body>
</html>

The alert in anonymous computed observable will fire not only when viewModel is created, but also each time a dependent observable (lastName in this case) is changed after constructor function is complete. In the code I'm maintaining right now this is used to run specific code to redraw bound ui widgets. So my questions are:

  1. Is this a bug in knockout which eventually be fixed? (So I'd better remove this magic whatsoever, before it will stop working after update)
  2. Is this a common pattern of sorts and perfectly fine to use?

UPDATE: In the real case I encountered in the project I need to maintain there are several lines of code in place of alert with no direct references to a dependent observable, value of observable is changed in some nested function calls made from within computed. The example given is extremely simplified. Also, both computed observables are decorated with throttle extender which is probably was sole purpose of making them computed in first place.

2
Why did you create the computed in the first place?haim770
What exactly are you expecting to happen? It's not a bug... that's exactly how a computed observable is supposed to work. The value is calculated on creation, and updates when other observables it depends on is updated.Jeff Mercado
I expect anonymous computed observable to be executed exactly once upon declaration. Since it's value cannot be read there is no point executing it anymore. I expect it to resemble pure computed behavior to an extent. No name > no subscribers > no execution.M-Kay
You are thinking of a computed observable as a value. While it can be that, there is no requirement stating it has to. Maybe it'll make it easier to think of a computed as a callback function. In the case of an anonymous computed, its like a callback function without a return value vs a named computed resembling a callback function that returns a value.user3619165

2 Answers

1
votes

When a function (including computed function) is reading the value of some observable, Knockout automatically creates a dependency between the two. Once the observable value has changed, all dependent functions will be re-evaluated.

However, you can explicitly instruct Knockout not to create a dependency using the peek() method:

ko.computed(function(){
    alert(self.lastName.peek());
});

See "How dependency tracking works"

0
votes

Of course, the computed function will call each time when there is a change in the value of any observable which used inside this function.

http://knockoutjs.com/documentation/computedObservables.html