clzola
clzola

Reputation: 2025

How to handle sequence observables with rxjs?

I have next scenario:

if (username exists in database)
    throw new Error(msg1);
if (email exists in database)
    throw new Error(msg2);
insertNewPlayer(username, email, password);

My environment is nodejs with TypeScript and I am using RxJS and MongoDB driver for nodejs. And I wrote next code:

return Observable.fromPromise(this.players.findOne({username: username}))
    .mergeMap(data => {
        if(data) throw new Error("That username is taken!");
        return Observable.fromPromise(this.players.findOne({email: email}));
    })
    .mergeMap(data => {
        if(data) throw new Error("That email is taken!");
        return Observable.fromPromise(this.players.insert(playerData));
    })
    .map(result => this.createNewPlayerFromData(playerData))

Since I am using MongoDB driver for nodejs I need to use .fromPromise so I can "cast" it to Observable...

Is this the correct way to do this? Or is there any other way? (Do not worry about createNewPlayerFromData function, it's just transforms playerData object to object of type Player)

Upvotes: 0

Views: 260

Answers (2)

Jecfish
Jecfish

Reputation: 4189

Or the other similar way, but in a sequential order would be:

const username$ = Observable
  .fromPromise(this.players.findOne({username: username}))
  .switchMap(x => x ? of(x) : _throw('That username is taken.'));

const email$ = Observable
  .fromPromise(this.players.findOne({email: email}))
  .switchMap(x => x ? of(x) : _throw('That email is taken.'));

const insertData = (data) => Observable
  .fromPromise(this.players.insert(playerData));

const insertPlayer$ = Observable.zip(
  username$, email$, (username, email) => ({ username, email }))
  .switchMap(data => insertData(data));

insertPlayer$.subscribe(x => this.createNewPlayerFromData(x));

Upvotes: 1

Jecfish
Jecfish

Reputation: 4189

I think you can use zip or combineLatest to accomplish the task above.

const username$ = Observable
  .fromPromise(this.players.findOne({username: username}));

const email$ = Observable
  .fromPromise(this.players.findOne({email: email}));

const insertData = (data) => Observable
  .fromPromise(this.players.insert(data));

Observable.zip(username$, email$, (username, email) => {
  if (!username) {
    throw new Error('That username is taken!');
  }

  if (!email) {
    throw new Error('That email is taken!');
  }

  return { username, email };
})
  .switchMap(data => insertData(data))
  .subscribe(x => {
     this.createNewPlayerFromData(x);
});

Upvotes: 0

Related Questions