Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

255
Vistas
Can this rxjs merge logic be simplified?

I have an observable (onAuthStateChanged) from the Firebase client that:

  1. emits null immediately if the user is not signed in, and
  2. emits null and then a user object a few moments later if the user is signed in.
const observable = new Observable((obs) => {
    return app.auth().onAuthStateChanged(
        obs.next,
        obs.error,
        obs.complete
    )
})

What I want is to:

  1. ignore any emitted null values for the first 1000ms of the app lifecycle (null coming after 1000ms is accepted)
  2. always emit user object regardless of what time it comes
  3. if no user object comes in the first 1000ms, then emit null at the 1000ms mark

Here is what I've done (and it seems to work). However, I'm reluctant to use this code as it doesn't seem that concise:

const o1 = observable.pipe(skipUntil(timer(1000)))

const o2 = observable.pipe(
    takeUntil(o1),
    filter((user) => user !== null)
)

const o3 = timer(1000).pipe(takeUntil(o2), mapTo(null))

merge(o1, o2, o3).subscribe({
    next: setUser,
    error: console.log,
    complete: () => console.log("error: obs completed, this shouldn't happen"),
})

Is there a way to do this without merge? I tried going through the docs but I'm quite lost.

Thanks for your help!

about 4 years ago · Juan Pablo Isaza
2 Respuestas
Responde la pregunta

0

You could use concat instead of merge. Think of it as using the first source until it completes, then use the second source.

const nonNullUser = firebaseUser.pipe(
    filter(user => user !== null),
    takeUntil(timer(1000))
);

const user = concat(nonNullUser, firebaseUser);

user.subscribe(...);

I just realized that this solution will not explicitly perform step #3 "emit null at the 1000ms mark". I was thinking subscribing to firebaseUser would emit the latest value. But, I'm not sure if that's true for your scenario.

If not, we could easily achieve this by adding shareReplay like this:

const firebaseUser = observable.pipe(shareReplay(1));
about 4 years ago · Juan Pablo Isaza Denunciar

0

While I liked the answer from @BizzyBob I was genuinely intrigued by these requirements that I wanted to see what other options were available. Here's what I produced:

const auth$ = observable.pipe(
    startWith(null)
)

const null$ = timer(1000).pipe(
    switchMap(_=>auth$)
)

const valid$ = auth$.pipe(
    filter(user=>!!user)
)

const user$ = race(null$, valid$);

We have our source auth$ observable which gets your Firebase data. However, startWith() will immediately emit null before any values coming from Firebase.

I declared two observables for null and non-null cases, null$ and valid$.

The null$ observable will subscribe to auth$ after 1000ms. When this happens it immediately emits null thanks to the startWith() operator.

The valid$ observable subscribes to auth$ immediately but only emits valid user data thanks to filter(). It won't emit startWith(null) because it is caught by the filter.

Last, we declare user$ by using the race() operator. This operator accepts a list of observables as its parameters. The first observable to emit a value wins and is the resulting subscription.

So in our race, valid$ has 1000ms to emit a valid user. If it doesn't, race() will subscribe to null$ resulting in the immediate null, and all future values coming from Firebase.

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda