Ricardo Saracino
Ricardo Saracino

Reputation: 1420

Rxjs synchronous?

I recently started working on a new project and I have seen this twice now, am I crazy or will never work under any circumstance?

protected get reportView(): any {
    let convertedView = null;
    this.store
      .pipe(select(fromStore.getTransferOrderConverted), rxjs.take(1))
      .subscribe((convertedOrder) => (convertedView = convertedOrder));
    return convertedView;
  }

Upvotes: 2

Views: 3260

Answers (4)

Pradeep Siva
Pradeep Siva

Reputation: 1

Rxjs take(1), first() operator should work absolutely fine

These 2 operators takes the latest value from store selector or BehaviourSubject in synchronous way.

Upvotes: 0

Mrk Sef
Mrk Sef

Reputation: 8022

am I crazy or will never work under any circumstance?

Q) Are you crazy?
A) Yes. Absolutely. That looks bonkers!

Q) Will this never work under any circumstance?
A) Oh, there are times this will work. Some observables are synchronous.

For example, this will always log a 2, so this works as expected.

let convertedView = null;

of(1).pipe(
    map(v => v + 1)
).subscribe(convertedOrder => convertedView = convertedOrder);

console.log(convertedView);

That's because of(1) is a synchronous observable.


This, however, will never work

let convertedView = null;

of(1).pipe(
    delay(0),
    map(v => v + 1)
).subscribe(convertedOrder => convertedView = convertedOrder);

console.log(convertedView);

This will print null. Even though delay(0) conceptually takes no time, it still uses JSs event loop and therefore doesn't get executed until the current code completes.


I think it's best practise to assume all observables are asynchronous. Any code that assume otherwise is likely to be brittle.

Upvotes: 3

Khanh Chau
Khanh Chau

Reputation: 121

Convert a stream to synchronous isn't a good ideal. However, you can use method toPromise of a subject (subscription) for convert it to a promise and await for resolve.

Upvotes: 0

Leandro Matilla
Leandro Matilla

Reputation: 1011

Your store.subscribe is asynchronous and the rest of your code is not. You can resolve it with a Promise like the example below.

protected get reportView(): Promise < any > {
    return new Promise((resolve, reject) => {
        this.store
            .pipe(select(fromStore.getTransferOrderConverted), rxjs.take(1))
            .subscribe((convertedOrder) => resolve(convertedOrder));
    });
}

reportView.then(convertedOrder => {
    // do your stuff
});

Also you can get the convertedOrder with Async/Await. But remember, the parent function must be async.

const convertedOrder = await reportView();

Upvotes: 1

Related Questions