2

Is it possible to ensure that a subscriber is the last to be executed in the observer queue? A delay(0) is no option for me since I need the code to be executed in line and not asynchrounus.

let observable = new Subject<void>();

//delay(0) no option!
observable.pipe().subscribe(() => console.log("I want to be last!"));
observable.subscribe(() => console.log("I want to be first!"));

observable.next();

I've created an example here: https://stackblitz.com/edit/rxjs-demo-xuf2ru

I want the first subscriber, to be executed last. The current console output is:

I want to be last!

I want to be first!

tris
  • 863
  • 4
  • 9
  • 22
  • Why do you care? If you have an issue with this, it hints at deeper problems. Subscribers should be independent. – Bergi Nov 01 '20 at 17:32
  • I need to call Angular's cdr after all events have been published. I can either call it after I call the subject or, what I think is way nicer, after the subject was invoked. But since it's not cdr specific I did not mention it for not confusing unnecessarily. – tris Nov 02 '20 at 09:34

2 Answers2

2

You may also use a common Subject as a means of communication between the observables as illustrated below:

const observable = new Subject<void>();
const commonSub$ = new Subject();

observable.pipe().subscribe(() => {
  commonSub$
    .subscribe(() => {
      console.log('I want to be last!');
    });
});

observable.subscribe(() => {
  console.log('I want to be first!');
  commonSub$.next(true);
});

observable.next();

Thereby, only after the second message is logged the first message will be logged.


As per your latest comment, you may use switchMap to ensure the same functionality is achieved for multiple events:

observable
   .switchMap(() => {
      return commonSub$;
   })
   .subscribe(() => {
      console.log("I want to be last!");
   });

observable.subscribe(() => {
   console.log("I want to be first!");
   commonSub$.next(true);
});
Nicholas K
  • 15,148
  • 7
  • 31
  • 57
0

You could create 2 observables with the desired output and then use the mergeMap operator to preserve the order.

const observable1 = Observable.of("I want to be first!");
const observable2 = Observable.of("I want to be last!");

observable1
  .mergeMap(x => {
    console.log(x);
    return observable2;
  })
  .subscribe(x => console.log(x));

Stackblitz example

EugenSunic
  • 13,162
  • 13
  • 64
  • 86
  • I like your idea but can't get it working. I modified it a bit to illustrate my problem: https://stackblitz.com/edit/rxjs-demo-q6cuxq I need "observable1" to be called many times (it is used as an external event). Now after all the subscribers are called I need to run my internal code. – tris Nov 02 '20 at 08:07