4

I have a particular knockout observable that's used in many computed functions and it works exactly as it's supposed to. However on one of these computed functions I do NOT want it to trigger when the observable is updated. Code wise it would look something like this:

  self.obs1 = ko.observable(foo);
  self.obs2 = ko.observable(bar);

  //I want this computed to behave normally
  this.comp1 = ko.computed(function() {
    return self.obs1() + self.obs2();
  }, this);

  //I want this computed to trigger on obs1 update but ignore updates to obs2
  this.comp2 = ko.computed(function() {
    return self.obs1() + self.obs2();
  }, self);

  setTimeout(function() {
    self.obs1(20);
    self.obs2(15);    
  }, 1000);

https://jsfiddle.net/r73yLk5u/

Note that I do still need to be able to access the current value of obs2 when comp2 is executed I just dont want the update of obs2 to trigger comp2 to have a new value.

Is this possible?

Nathan
  • 295
  • 2
  • 13
  • Ugh, I don't know if it's possible, but it probably is with some custom extender or something. I do think this is a sign that something is wrong, however, and before you go ahead and do it, re-examine _why_ you want that and if you aren't trying to solve an [XY problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). – VLAZ Oct 28 '16 at 18:28
  • Thanks @vlaz. You're probably right on that I just didn't want to get too bogged down on the context . The short of it is basically that my UI is refreshing too much but I cant just use a rateLimit since I want to see updates to 'obs1' almost immediately but 'obs2', which is updated very frequently, I never really care about. – Nathan Oct 28 '16 at 18:45
  • Have you considered using `.extend({throttle: /* some reasonable value */ })` on the second observable, then? – VLAZ Oct 28 '16 at 18:48
  • Wish I could but the other computeds that use the 2nd observable definitely need to be triggered on update immediately. Thanks anyways! – Nathan Oct 28 '16 at 20:37
  • ..actually that totally will work so long as the update is on a secondary computed rather than the observable itself – Nathan Oct 28 '16 at 20:46
  • Yeah, sorry, I did mean the second computed. Mixed up computed/observable :/ – VLAZ Oct 28 '16 at 21:01

2 Answers2

4

To make it ignore updates to an observable, use peek (docs):

The peek function lets you access an observable or computed observable without creating a dependency.

Updated example:

//I want this computed to trigger on obs1 update but ignore updates to obs2
  this.comp2 = ko.computed(function() {
    return self.obs1() + self.obs2.peek();
  }, self);

https://jsfiddle.net/r73yLk5u/2/

Michael Best
  • 16,378
  • 1
  • 33
  • 66
0

Okay so I figured out how to do this. If you create a new computed which only returns the observable you want to delay then rateLimit it to a point that it will never hit you can just use that computed in place of the observable. This will also make it always use the up-to-date obs2 value should the computed get triggered for any other reason in the future.

  self.obs2DelayComp = ko.computed(function() {
    return self.obs2();
  }).extend({ rateLimit: 3001 });

https://jsfiddle.net/r73yLk5u/1/

Nathan
  • 295
  • 2
  • 13