lzl124631x
lzl124631x

Reputation: 4779

Knockout bindingHandler causes pureComputed evaluation delay

I found that my bindingHandler causes unexpected pureComputed evaluation delay.

Demo here

Without binding handler

Without binding handler (simply comment the HTML out), I see the following log:

In subscription, new value is (newName), nameComputed is (newNameComputed)

As you can see, in the subscription, the computed was evaluated to the latest value.

With binding handler

With binding handler, I see the following log:

Evaluation in bindingHandler oldNameComputed
In subscription, new value is (newName), nameComputed is (oldNameComputed)
Evaluation in bindingHandler newNameComputed

As you can see, in the subscription, the computed was still using the old value (oldNameComputed), and in the next evaluation it's evaluated to latest value (newNameComputed)

Question

This is unexpected to me -- adding the binding handler changes the evaluation behavior.


Update 12/26/2019

Adding a bit context. My nameComputed is actually nameError which processes the name and detects whether the input is allowed or has errors (e.g. no special character, nonempty, max length etc).

In the subscription, I wanted to do some ajax calls if there is no name error. So I looked at the value of nameError and only fires the requests if there is no error.

But with the binding handler, my nameError check is outdated.

Yes, I do have the latest name value in the subscription, but I need to call the name error check function again to get the latest nameError value instead of directly using nameError computed value.

Upvotes: 1

Views: 68

Answers (1)

lzl124631x
lzl124631x

Reputation: 4779

Credit to mbest in Github Issue

The first section in the pure computed documentation describes its two states. The difference you see in behavior is because the pure computed is in a different state. Without the binding handler, it is in the sleeping state, and with the binding handler, it is in the awake state.

It is normal that a subscription can run while state is being updated, and thus not all computed observables have been updated with the latest value. The main way to work around this is use deferred updates. If you set ko.options.deferUpdates = true;, you will get the results you want.


I might not go in this route for now because I'm working on a big project and don't want to introduce this global level change for now.

Upvotes: 1

Related Questions