Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

261
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda