Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RxJS: Difference between auditTime and sampleTime?

I can't find any relevant posts about this and I can't figure out the nuance from the documentation, what is the difference between auditTime and sampleTime operators?

like image 941
miikalo Avatar asked Jan 25 '23 02:01

miikalo


1 Answers

auditTime

auditTime(ms) will keep storing the latest value for ms milliseconds. After ms have passed, if any value exists, it will pass along as a next notification.

auditTime(ms) === audit(() => timer(ms, scheduler?)).

u - units of time

1--3--5----------6-7-- values$
----|-----|----!-----| auditTime(5u)
----3-----5----------7 result

^     ^          ^

! - since the timer did not started, because there was no value after `5`, there won't be any value emitted further in the stream

^ - when the timer starts

It's also worth noticing that this timer starts only when at least one value has arrived.

Maybe visualizing the source code would help:

_next(value: T): void {
  this.value = value; // Keep track of the oldest value
  this.hasValue = true;
  if (!this.throttled) { // If the timer didn't started yet, start it
    let duration;
    try {
      const { durationSelector } = this;
      duration = durationSelector(value); // Create observable; if `auditTime(d)`, it will be `() => timer(ms)`
    } catch (err) {
      return this.destination.error(err);
    }
    const innerSubscription = subscribeToResult(this, duration); // Subscribe to the inner observable
    /* ... */
    this.throttled = innerSubscription // Store the subscription
  }
}

When the timer expires(i.e when the inner observable has emitted/completed), the value will be passed along:

// Called when the inner obs completes/emits a value
clearThrottle() {
  const { value, hasValue, throttled } = this;
  if (throttled) { // Did we have a timer(a subscription)? If yes, unsubscribe 
    this.remove(throttled);
    this.throttled = null;
    throttled.unsubscribe();
  }
  if (hasValue) { // If we have a value, send it do its destination
    this.value = null;
    this.hasValue = false;
    this.destination.next(value);
  }
}

sampleTime

sampleTime(ms), like auditTime(ms) will keep track of the latest arrived value and will emit it further in the chain, with the exception that in sampleTime the timer(which decides when to emit the value) is always active. This means that no matter if any value as arrived since the last emission, the timer will run. Now, if no new value arrived, it will simply not pass along the value.

Let's explore its source code:

_next(value: T) { // Keep track of the oldest value
  this.lastValue = value;
  this.hasValue = true;
}

notifyNext() { // When time is up, check if any `new` value came in since the last 'sample' 
  if (this.hasValue) { // If we have a value, then send it further
    this.hasValue = false;
    this.destination.next(this.lastValue);
  }
}

Note that the value can be the same as the one which was previously emitted, but it must arrive while the current timer is active.

sampleTime by default uses AsyncActions, which are managed by the AsyncScheduler. Put differently, the timer, in this case, is achieved with setInterval.

sample(notifier) follows the same logic, except that there is no scheduler, and the timer is defined by the notifier, which is an Observable.

Compared to auditTime:

u - units of time

1--3--5-------6-7-- values$
----|---|---|---|-- auditTime(5u)
----3---5-------7-- result

^   ^   ^   ^   ^

^ - when the timer starts
like image 84
Andrei Gătej Avatar answered Feb 07 '23 19:02

Andrei Gătej