Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • 10:17
    jakovljevic-mladen commented #6470
  • 10:16
    jakovljevic-mladen edited #6470
  • 05:21
    cartant commented #6477
  • Jun 15 13:34
    ekasprzyk opened #6477
  • Jun 14 15:41
    kwonoj locked #6475
  • Jun 14 15:41
    kwonoj closed #6475
  • Jun 14 15:07
    Thaina edited #6475
  • Jun 14 15:07
    Thaina edited #6475
  • Jun 14 15:05
    Thaina edited #6475
  • Jun 14 15:03
    Thaina opened #6475
  • Jun 14 14:43
    leggechr commented #6472
  • Jun 14 08:32
    ronag opened #6474
  • Jun 12 18:20
    paulmojicatech synchronize #5997
  • Jun 11 20:56
    dependabot[bot] labeled #6473
  • Jun 11 20:56

    dependabot[bot] on npm_and_yarn

    chore(deps): bump normalize-url… (compare)

  • Jun 11 20:56
    dependabot[bot] opened #6473
  • Jun 11 20:10
    benlesh synchronize #6472
  • Jun 11 20:05
    benlesh synchronize #6472
  • Jun 11 20:02
    benlesh commented #6472
  • Jun 11 20:02
    benlesh review_requested #6472
Ramon P.
@AlteredCarbonate

@Dorus https://gist.github.com/AlteredCarbonate/86af506d32558c35653db50fc1881796
I'll just share it here <-<
A friend told me, who is frequently in touch with RxJS. That I did a lot things, already possible in RxJS itself.
But there're just to many Operators, and I still try to stick with the Promisebased Structure (And then, And then, And then...) ^_^

Any help is welcome <3

Dorus
@Dorus

@AlteredCarbonate a couple things (i only looked 3 seconds). Do not nest subscribe, instead flatten the stream using the flatmap operators like mergeMap, switchMap, concatMap, exhaustMap. They all allow you to flatten the stream, but each has different concurrent behavior
Thus, if you do source.map(e => someRequest(e)) you would get Observable<Observable<result>>, but with source.mergeMap(e => someRequest(e)) you would get the flattened result: Observable<Result>.
That way, you only need to subscribe at the end of your pipe. Better: Often you do not need to subscribe at all, you can write functions that return observable (like the someRequest function in my example).
Also you shouldnt need new Observable, at least not too much. There are many creating operators. If you are overwhelmed by them, use the decission tree to find the right one.
If you do use new Observable, you could make use of the cleanup callback you're allowed to return from the onSubscribe function.

new Observable(ob => {
  let i = 0;
  let t = setInterval(() => ob.next(i++), 1000);
  return () => clearTimeout(t);
}).pipe(take(5))

Here i take advantage of the take(5) operator to cancel the endless observable i made, making it call clearTimeout(t) after 5 emissions.
Also this could be even shorter with interval(1000).pipe(take(5)).

Ramon P.
@AlteredCarbonate
Omg.
Thank you very much, I'll try to rework it with your given links.
But Is a bit overwhelming 🤣🤣
Dorus
@Dorus
@AlteredCarbonate No worries :) Take it slowly and feel free to come back if you have more questions.
Nico
@ndcunningham
hey all!
is it possible to have two observable one (obA$) starts off the stream
the other observable (obB$) is then kicked off to start emitting until a valid value is emitted.
obB$ then stops emitting and is restarted again when obA$ emits again
Nico
@ndcunningham
think i found it out !
Dorus
@Dorus
@ndcunningham obA$.pipe(switchMapTo(obB$.pipe(first(isValid.bind(this))))), where isValid is a function that decide if the value valid.
first <-> find could be exchanged depending on your need
Nico
@ndcunningham
hmm never used switchMapTo before but i just did a
obA$.pipe(mergeMap(aResult => obB$.pipe(filter(foo => isValid(foo)),take(1), map(bResult => ({ aResult, bResult})))
Something like this
Dorus
@Dorus
@ndcunningham Ah i didnt realize you needed to combine the a and b result. In that case xxxMapTo wont work.
And filter+take(1) can be combined in find.
Pretty much the same solution beside those differences
Nico
@ndcunningham
oh find
should've thought of that :sweat_smile:
Nico
@ndcunningham
I have two observables merge(this.msalBroadcastService.inProgress$, this.msalBroadcastService.msalSubject$)
If neither fires after a second i want to fallback to a default value anyway i could do this
like a delayed startWith
i guess i could just merge a timer
Dorus
@Dorus

@ndcunningham if you merge with a timer, the timer will always go off. Is that intended?

Asumeing your original merge is source:

source.share(src => merge(timer(n).pipe(takeUntil(src)), src))

could work, this will cancel the timer when src emit. This will only work for the very first emission.
I could also modify it to work repetitively after the source has not emitted for 1 second:

source.share(src => merge(src.pipe(debounceTime(n), mapTo(value))), src)

here value is the fallback default.

Andrew Vorobyov
@santacruz123
How can this be achieved with operators
return new Observable(sub => {
    let ohlc = {}
    let last = Math.round(new Date().getTime() / 1000)

    return trades$.subscribe(trade => {
      const curr = Math.floor(trade.timestamp / 1000)

      if (curr > last) {
        sub.next(ohlc)
        ohlc = {}
        last = curr
      }

      ohlc = {
        t: ohlc.t ? ohlc.t : curr,
        o: ohlc.o ? ohlc.o : trade.price,
        h: trade.price > ohlc.h || !ohlc.h ? trade.price : ohlc.h,
        l: trade.price < ohlc.l || !ohlc.l ? trade.price : ohlc.l,
        c: trade.price,
        v: ohlc.v || 0 + trade.amount,
      }
    })
  })
Dorus
@Dorus
@santacruz123 look at a combination of scan and auditTime
oh i see what you're trying to do. windowTime might also be a good one
trades$.pipe(
  windowTime(1000),
  mergeMap(window => window.pipe(|
    reduce((ohlc, trade) => ({
      t: ohlc.t ? ohlc.t : Math.floor(trade.timestamp / 1000),
      o: ohlc.o ? ohlc.o : trade.price,
      h: trade.price > ohlc.h || !ohlc.h ? trade.price : ohlc.h,
      l: trade.price < ohlc.l || !ohlc.l ? trade.price : ohlc.l,
      c: trade.price,
      v: ohlc.v || 0 + trade.amount,
    }), {})
  ))
)
softshipper
@softshipper
Hi all
I bought the RXJS course from https://app.ultimatecourses.com/. When I download the video and play it with VLC the quality is very
2 replies
Screenshot from 2021-05-20 23-30-35.png
Has anyone the same experience?
Dorus
@Dorus
afbeelding.png
Nico
@ndcunningham

@ndcunningham if you merge with a timer, the timer will always go off. Is that intended?

Asumeing your original merge is source:

source.share(src => merge(timer(n).pipe(takeUntil(src)), src))

could work, this will cancel the timer when src emit. This will only work for the very first emission.
I could also modify it to work repetitively after the source has not emitted for 1 second:

source.share(src => merge(src.pipe(debounceTime(n), mapTo(value))), src)

here value is the fallback default.

@Dorus yes i always want the timer to go off if i get no response in x seconds then the emission from the timer tears down the subscription and also has logic to navigate somewhere else

Sarang Kartikey
@sarangkartikey50
Hey guys! Is there any resource available to check the browser/node support of RxJS?
Paolo de Dios
@paolodedios_twitter
image.png
Kamil
@Chester97
Hi guys, is there any way to invoke two inputs values on button click? For example: You have to type your name into one input and surname into second input. Then display input values on button click. The main problem is: how to connect 3 stream(fromEvents) which are: change,change,click.
Nico
@ndcunningham
@Chester97 you need to map over each event over all the inputs that fire them
Lazar Ljubenović
@lazarljubenovic
3 replies
Kamil
@Chester97
Hi guys, I'm learning RxJS and I have some small problems. In my test project I've created 2 inputs and one button. I have added some logic to those inputs, then I combine those into 1 stream using combineLatest my goal is get value from combineLatest on button click which is another fromEvent = stream. How can I do this?
Here's code: https://gist.github.com/Chester97/0519651367ae9c4f3e6050bd5cf2fe09
8 replies
Bogomip
@Bogomip

Hi all, so I am working on a login function using firebase and have three observables I want to return as one, but must run in order - so:
Observable 1 runs, if it fails it returns an error and if it succeeds it goes on. Observable 2 runs, same error conditions, Observable 3 runs, same error conditions. I have code which looks like this right now:

login(email: string, password: string): Observable<any> {
       // observable 1 - works properly
       return from(this.fAuth.signInWithEmailAndPassword(email, password)).pipe(take(1), catchError(this.handleError), tap((result: any) => {

                  // observable 2    - does not work properly. from used to convert from a Promise into an Observable
                   return from(this.firebase.collection('users').doc(result.user.uid).get()).pipe(take(1), catchError(this.handleError), tap((doc: any) => {

                           // observable 3    - does not work properly.
                           return result.user.getIdTokenResult(true).pipe(take(1), catchError(this.handleError), tap((token: any) => {
                                   // do stuff
                           }));
                   }));
               }));
           }

but its only currently returning the first observable and not allowing error conditions for the nested two observables. Any suggestions for how I can properly merge these whilst retaining access in subsequent observables to the return values of the previous observables?

Dorus
@Dorus
@Bogomip To combine observable, depending on if the next one uses the results of the previous one you can pick mergeMap familiy (switchMap, concatMap etc), or use concat/merge, if they do not need the previous result.
ob1().pipe(
  mergeMap(result => concat(ob2(result), ob3()))
)
Here ob2 depends on ob1, but ob3 merely waits for ob1 and ob2 to complete without errors.
Bogomip
@Bogomip

@Dorus Thanks a bunch, mergemap works really well for this when everything goes well... but when there is an error (which happens on the second in the chain more often) it comes up with an array which runs for every character in the string, i.e. it iterates 40+ times because its a map with result = e, r, r, o, r... etc.

Is there an alternative to mergeMap which works in the same way but returns the value as a whole - or a better way of taking that result as one object using typescript which I need to learn? :)

5 replies
Jorrit
@jorrit-wehelp
sounds to me it would be better to fix the error handling underneath and prevent that from happening altogether
Dominic Watson
@intellix
I've got an array of observables and I want them to emit one after another... It seems really basic but i can't think for the life of me how to do it. This makes them all happen at the same time:
merge(
  timer(1000).pipe(map(() => 1)),
  timer(1000).pipe(map(() => 2)),
  timer(1000).pipe(map(() => 3)),
)
oh... it's literally merge -> concat. I've never had to use that so it wasn't fresh off the top of my head
Dorus
@Dorus
@intellix Yes correct answer :D
Filip Krawczyk
@filipkrw
Is it possible to create a new observable from each value of another observable? Let's say I have this observable:
const spawnEnemy$ = interval(2000).pipe(
  map(() => {
    return new Observable((subscriber) => {
      const enemy: Enemy = new Enemy(two, player.getPosition())
      subscriber.next(enemy)
    })
  })
)
For every enemy, I'd like to update its position based on another observable (which sends a value on every frame paint). If certain conditions are met, I'd like the enemy observable to complete.
The only way I imagine doing this is to treat every enemy as a separate observable.
1 reply
danilaapp
@danilaapp

Hello. Help solve the problem, I have been reading the documentation for 3 days ... I cannot find a solution ...

Situation: when the screen rotates on the phone, then 3 events are triggered with a difference of 50-100ms: they can be caught like this:
const stream $ = zip ([fromEvent (window, 'resize'), fromEvent (visualViewport, 'resize'), fromEvent (window, 'orientationchange')]). In other words, the handler will execute if all three events were raised.

But when the keyboard opens, one visualViewport (resize) event is triggered.

If you hang a separate handler on the visualViewport event + a handler on the zip, then when the screen is rotated, the visualViewport handler will be falsely triggered, because it is included in the zip observer.

I need to clearly determine whether the screen has rotated or the keyboard has opened.

This can be done by making sure that only the visualViewport event has been triggered and the window (orientationchange and resize) events have not occurred in the immediate vicinity.
How can I write this in rxjs? Help

Dorus
@Dorus

@danilaapp Many ways to do this. zip will only wait for all events to happen, so might not be the best operator here. It'll also buffers duplicate events and is best used for events that are all raised an equal number of times.

What i guess you want is to wait for 2 events and reset when 2 others are not emitting inbetween? You also mention something about timing that can be added, but your specs arn't too clear. But let me show some examples:

let reset = merge(ob1, ob2).pipe(startWith(null));
let trigger = forJoin(ob3, ob4);
let stream = reset.pipe(switchMapTo(trigger));

This example will reset on ob 1 or 2 events, but trigger when both ob3 and ob4 have triggered without ob1 and ob2 doing so inbetween.

Dorus
@Dorus

if you want trigger to reset after 1 second, try

trigger = ob3.pipe(publish(src3 => ob4.pipe(publish(src4 =>
  merge(src3, src4).pipe(debounceTime(1000), switchMapTo(forkJoin(src3, src4)))
  ))))

This one is a bit comlpictated, but what i'm doing is listening to ob3 and ob4 twice, so i use publish to pipe them trough a subject before subscribing twice. I'm 80% sure there is a nicer way to do this, but cannot come up with one now (the complication is i want either of them to go first, if there is an order it's easy, just listen to the first one and switchMap to the second ob3.pipe(switchMapTo(ob4.pipe(takeUntil(timer(1000))))))

danilaapp
@danilaapp
@Dorus thanks, you helped me a lot :)