1

I have the following code

this.someFormGroup.controls['control1'].valueChanges.subscribe(val => {
   if (val) {
      doStuff();
   }
   setTimeout(() => doOtherStuff(), 1000);
});

I am wondering if there is another way to achieve this without the use of setTimeout, I was thinking about timer from rxjs, but I am not sure how that could be incorporated here.

AngularDebutant
  • 1,436
  • 5
  • 19
  • 41

2 Answers2

2

Altough the above solution works, pipe side effects are never the solution you want to go for. One of the big advantages at Rx is that you always know what happens, when and how. There are lot's of articles around why you should not use side effects in general:

Also keep in mind: It is always, really always possible to implement solutions without tap and most of the times it's pretty easy as you can see down.

private readonly valueChanges$: Observable<any> = this.someFormGroup.controls['control1'].valueChanges

private readonly delayedValuechanges$: Observable<any> = this.valueChanges$.pipe(
  delay(1000)
)

constructor(private readonly someFormGroup: SomeFormGroup) {
  this.valueChanges$.subscribe(this.doStuff);
  this.delayedValueChanges$.subscribe(this.doOtherStuff);
}
Jonathan Stellwag
  • 3,843
  • 4
  • 25
  • 50
0

You can use tap and delay:

this.someFormGroup.controls['control1'].valueChanges
  .pipe(
    tap(val => {
      if (val) {
        doStuff();
      }
    }),
    delay(1000),
  )
  .subscribe(() => doOtherStuff());
martin
  • 93,354
  • 25
  • 191
  • 226
  • It's a bad practice to implement side effects in rx pipes. I would avoid this solution. I provided an answer with two links why it's bad. You can find lot's of articles around clean code, side effects. If you want to know it in detail I recommend reading: Clean Code, Robert Martin – Jonathan Stellwag Feb 14 '20 at 06:06
  • tap() operator’s only purpose is to make side-effects and in practice its impossible to create RxJS chains without side-effects. That’s why you have a special operator for that and you don’t make side-effects inside ‘map()’ for example. This is why tap() in RxJS core https://rxjs.dev/api/operators/tap – martin Feb 14 '20 at 07:35
  • You can write bad code in JavaScript in general. Only the language or framework supports functions/operations does not mean it is a good practice. The goal of rx and clean programming is to move the side effect as far as possible to the end. That always means into the subscription. If you are working in a bigger project, pipes with side effects cause your system to be maintained in a very time consuming way. – Jonathan Stellwag Feb 14 '20 at 09:52
  • 2
    Well, I have 1000 answers on this site tagged with "rxjs" and I don't want to discourage you but you're about to be very disappointed with RxJS because sticking blindlessly to a rule that wasn't created for reactive programming in the first place (!) will lead you to absolutely ridiculously complicated solutions. The book you suggested (I actually know this book very well) also recommends writing methods with max 4 line of code and that you should use Occam's razor when there're more way to to solve one thing. So you can take whatever you want from that :). – martin Feb 14 '20 at 10:48
  • First: 1000 answers in rx does not in general mean you are right. I did not say your code does not work. Second: It's a general bad approach that should not be adviced to unexperienced rx programmer. Just making code work does not mean it's good. Thirdly: Not using side effects in pipes will not lead to complicated solutions in general and over time it will improve your code maintainability. Fourth: If you have 1000 answers in rx it's sad that you provide such solutions :) – Jonathan Stellwag Feb 14 '20 at 12:59