About "Using concat", you can put "startWith()" at the end, after "distinctUntilChanged()" and the startWith would behave as you would expect, aka it would not go through the debounceTime
This was really an eye-opener for me. I knew a thing or two about how to handle data with rxjs but there's so much to learn. It is amazing. Thanks a lot! I hope I can see more rxjs content.
I recently realized I need to deepen my understanding with Rxjs and your videos have been gold. Thank you for serving these cases with proper examples, keep it up!
That was an excellent explanation of the span operator. I use it in my apps for CRUD operations but I was struggling to explain how it was working as elegantly as you did.
I'm only just studying programming, but when I hear that rxjs has more than 100 operators, it makes me more excited to learn about all of them than nervous.
🤯 Hard to imagine how difficult it would be to do the same without rxjs! Scan is such a cool operator. Suggestion: We could set a default value when initialising the formControl, e.g new FormControl('gifs'), then instead of having of('gifs'), we can have, of(subredditFormControl.value). This way, the user can know what word was searched for the first results displayed. Keep up the great content, Josh 👍🏾.
9:17 looks weird. So we are using "gifs" as the starting point, but the form input does not show that. And you were right couple minutes earlier. It indeed looks like madness. I wonder if this added complexity has any advantage? Amount of nested code looks like something that a person fresh from collage would wrote as the first program. What would be advantage of using this approach over something like Vue or Svelte? Even simple operations like getting a parameter into a reactive variable look complex. RxJs const my_value$ = some_value$.pipe(map(s => s.variable), distincUntilChanged()) Vue const my_value = computed(() => some_value.variable) Svelte $: my_value = some_value.variable
This video is probably the most succinct explanation I can offer that describes the why of RxJS: ruclips.net/video/-CoVmNvp_1g/видео.html - in short, if you want to be reactive/declarative and you also want to handle async reactivity then you are going to need RxJS or something that does the same things as RxJS. Svelte, Solid etc. don't handle asynchronous reactivity by default
I built this app with TDD so I do just have the tests sitting there, so I might do a vid on it! Although I was thinking of doing a more broad testing vid. In general though I test this just like everything else - I take a black box approach so it's not like I'm testing individual operators, I just subscribe to the resulting stream in my tests and assert what should happen under certain conditions. For example, in one of my tests I mock some settings that require 15 gifs per page, and I will provide a mock http response that only provides 4. Then in my test I will expect that the gifs stream still gives me 15 gifs. So my tests don't care how something is being done (e.g. that the expand operator is being used) they only care about the result.
Great video! It was great to get an introduction to expand and scan. EDIT: What I said below is wrong. Sorry for the misinformation! Something to note: combineLatest will be removed in RxJS v8. I've been slowly replacing it with combineLatestWith to prepare.
Hi Joshua - I learned a lot on this video. Hopefully you can give to us it's repository link so I can debug it step by step. There's a part I'm still confuse.
Questions: does the use of RxJS really necessary for this specific problem? Does it overcomplicate the solution? Is it harder if it was implemented non reactively? What can you when doing this complex RxJS within a team, is it sustainable? Sorry for a lot of questions. Great content. 🤩
Maybe I'll do a video comparing this stream to a non-RxJS version of the same thing. Your questions are too big to give good answers to here, but I'll give some brief thoughts. Is it necessary? No, there are many ways you could do this and people have built things without RxJS for a long time (and still do). Does it overcomplicate? I think it simplifies - with this approach I can do more, in a safer way, with less code. But, if you don't have strong RxJS knowledge then you might consider it complicated. Is it harder to implement non reactively? That depends - again, someone without strong RxJS knowledge would probably have an easier time building this in a different way. Is it sustainable? It is if your team knows RxJS - I would say most frameworks or libraries won't work well in a team environment if the people on the team don't know how to use them.
@@JoshuaMorony thanks for your response. Make sense. So RxJS is just like a programming style, an options for devs to do functional programming. Looking forward to that comparison video. It's good to have comparison so that newbies (like me) can appreciate the power of RxJS. Thanks. 🤙
consider wrapping the extend on a defer operator to make it a cold observable with an internal state so you can keep the variable gifsRequested on the body of the defer operator and so you don't need to pass it through the fetchFromRedit function
Hi Joshua, thanks for a such a great real world example. I have only one question here: Does this stream even stop? For example if there is no GIFs left?
I have a question, why do you nest pipes inside your operators? I thought you could just chain operators inside the one pipe and in the end just subscribe or use the async pipe
although the explanation was good ..but request you to use streams diagrams which will change game all together while explaining rxjs operators functionality
Hi Josh! Great explanation and display of all the different operators used here. One question though, did you think about the case that the recursive part could produce more gifs than requested in the page size? Since this is an infinite scroll it could probably be ignored, but if it was a page with an exact size it would look a bit strange having, for example, 33/30 results.
I'd have to get my head back in this code again to be sure, but I'm pretty sure I set it up so that the `gifsRequired` being passed in will accurately reflect how many should be fetched, e.g. if we have 27/30 on the next run the gifsRequired will be 3 and it will only fetch that many
As per my understanding you get 100 posts from the API and take only the gifs from those posts, which lets say would be 20. Then you have 20/30 and you'll get another 100 posts where you end up with 15 gifs. So you have 35/30. Now I've missed the bit where you use gifs.slice(0, settings.perPage) in a map to never return more than the requested number of gifs. So my question is actually answered, sorry :) Although now it's necessary to consider the correct place to assign the after value in the paging. If you'd use the last gif from the last API call (number 35) you would miss 5 gifs from the thread on the next page. But I think you probably using the last gif after slicing, so thats fine. Would then just be a very slight efficiency optimization to cache the 5 gifs that were thrown away before, to not load them twice. But thats probably not important here ;)
Nope, whatever streams you give it concat will just wait for the first stream to complete (emitting all its values) and then it will subscribe to the next stream you gave it (emit all those values), and then the next stream and so on. If you just want emissions from any of the streams whenever they emit (rather than being ordered like with concat) then you might want to use something like merge instead.
About "Using concat", you can put "startWith()" at the end, after "distinctUntilChanged()" and the startWith would behave as you would expect, aka it would not go through the debounceTime
Oh nice, I'll give that a go - thanks!
Love this type of content. Going in-depth on all these cool rxjs operators is a lot of fun.
Thanks :)
This was really an eye-opener for me. I knew a thing or two about how to handle data with rxjs but there's so much to learn. It is amazing. Thanks a lot!
I hope I can see more rxjs content.
These tutorials are genius. Thanks Josh!
RxJS is such a headache to wrap my head around 😂😂
Especially because of a lack of real world examples.
So, thank you for this.
I recently realized I need to deepen my understanding with Rxjs and your videos have been gold. Thank you for serving these cases with proper examples, keep it up!
Another great video - I've not used scan or expand (or reduce) either. Good to get a clear explanation of them.
That was an excellent explanation of the span operator. I use it in my apps for CRUD operations but I was struggling to explain how it was working as elegantly as you did.
I'm only just studying programming, but when I hear that rxjs has more than 100 operators, it makes me more excited to learn about all of them than nervous.
Wow. That was such a good video. Very good explanation.
Im glad i found your chanel :) thank you for great content
I love your content!
🤯 Hard to imagine how difficult it would be to do the same without rxjs! Scan is such a cool operator.
Suggestion: We could set a default value when initialising the formControl, e.g new FormControl('gifs'), then instead of having of('gifs'), we can have, of(subredditFormControl.value). This way, the user can know what word was searched for the first results displayed.
Keep up the great content, Josh 👍🏾.
That's a great suggestion, I'll combine that with Chau's suggestion regarding the concat!
9:17 looks weird.
So we are using "gifs" as the starting point, but the form input does not show that.
And you were right couple minutes earlier. It indeed looks like madness. I wonder if this added complexity has any advantage?
Amount of nested code looks like something that a person fresh from collage would wrote as the first program.
What would be advantage of using this approach over something like Vue or Svelte?
Even simple operations like getting a parameter into a reactive variable look complex.
RxJs
const my_value$ = some_value$.pipe(map(s => s.variable), distincUntilChanged())
Vue
const my_value = computed(() => some_value.variable)
Svelte
$: my_value = some_value.variable
This video is probably the most succinct explanation I can offer that describes the why of RxJS: ruclips.net/video/-CoVmNvp_1g/видео.html - in short, if you want to be reactive/declarative and you also want to handle async reactivity then you are going to need RxJS or something that does the same things as RxJS. Svelte, Solid etc. don't handle asynchronous reactivity by default
Niceee!! Thanks for the content
Hey Josh, great video! Would you mind to do a video of how to unit test this kind of stream?
I built this app with TDD so I do just have the tests sitting there, so I might do a vid on it! Although I was thinking of doing a more broad testing vid. In general though I test this just like everything else - I take a black box approach so it's not like I'm testing individual operators, I just subscribe to the resulting stream in my tests and assert what should happen under certain conditions. For example, in one of my tests I mock some settings that require 15 gifs per page, and I will provide a mock http response that only provides 4. Then in my test I will expect that the gifs stream still gives me 15 gifs. So my tests don't care how something is being done (e.g. that the expand operator is being used) they only care about the result.
Love your content
Great video! It was great to get an introduction to expand and scan.
EDIT: What I said below is wrong. Sorry for the misinformation!
Something to note: combineLatest will be removed in RxJS v8. I've been slowly replacing it with combineLatestWith to prepare.
combineLatest the operator is being removed. combineLatest the function isn’t
@@ChauTran Thanks for the correction! I saw something about it in the docs but must not have notice what page I was on.
Hi Joshua - I learned a lot on this video. Hopefully you can give to us it's repository link so I can debug it step by step. There's a part I'm still confuse.
Questions: does the use of RxJS really necessary for this specific problem? Does it overcomplicate the solution? Is it harder if it was implemented non reactively? What can you when doing this complex RxJS within a team, is it sustainable?
Sorry for a lot of questions. Great content. 🤩
Maybe I'll do a video comparing this stream to a non-RxJS version of the same thing. Your questions are too big to give good answers to here, but I'll give some brief thoughts.
Is it necessary? No, there are many ways you could do this and people have built things without RxJS for a long time (and still do).
Does it overcomplicate? I think it simplifies - with this approach I can do more, in a safer way, with less code. But, if you don't have strong RxJS knowledge then you might consider it complicated.
Is it harder to implement non reactively? That depends - again, someone without strong RxJS knowledge would probably have an easier time building this in a different way.
Is it sustainable? It is if your team knows RxJS - I would say most frameworks or libraries won't work well in a team environment if the people on the team don't know how to use them.
@@JoshuaMorony thanks for your response. Make sense. So RxJS is just like a programming style, an options for devs to do functional programming.
Looking forward to that comparison video. It's good to have comparison so that newbies (like me) can appreciate the power of RxJS.
Thanks. 🤙
consider wrapping the extend on a defer operator to make it a cold observable with an internal state so you can keep the variable gifsRequested on the body of the defer operator and so you don't need to pass it through the fetchFromRedit function
Thank you for the suggestion! I'll look into this
Hi Joshua, thanks for a such a great real world example.
I have only one question here:
Does this stream even stop? For example if there is no GIFs left?
I have a question, why do you nest pipes inside your operators? I thought you could just chain operators inside the one pipe and in the end just subscribe or use the async pipe
Quick question, why're u using triple map operator there, while u can just use one to combine those values ?
although the explanation was good ..but request you to use streams diagrams which will change game all together while explaining rxjs operators functionality
github of this code? i would like to see the whole code... tks!!!
Hi Josh! Great explanation and display of all the different operators used here. One question though, did you think about the case that the recursive part could produce more gifs than requested in the page size? Since this is an infinite scroll it could probably be ignored, but if it was a page with an exact size it would look a bit strange having, for example, 33/30 results.
I'd have to get my head back in this code again to be sure, but I'm pretty sure I set it up so that the `gifsRequired` being passed in will accurately reflect how many should be fetched, e.g. if we have 27/30 on the next run the gifsRequired will be 3 and it will only fetch that many
As per my understanding you get 100 posts from the API and take only the gifs from those posts, which lets say would be 20. Then you have 20/30 and you'll get another 100 posts where you end up with 15 gifs. So you have 35/30.
Now I've missed the bit where you use gifs.slice(0, settings.perPage) in a map to never return more than the requested number of gifs. So my question is actually answered, sorry :)
Although now it's necessary to consider the correct place to assign the after value in the paging. If you'd use the last gif from the last API call (number 35) you would miss 5 gifs from the thread on the next page. But I think you probably using the last gif after slicing, so thats fine. Would then just be a very slight efficiency optimization to cache the 5 gifs that were thrown away before, to not load them twice. But thats probably not important here ;)
1:49 Kaysh - cache = cash.
Hey Josh, does it matter what observable stream you are piping when you concat another stream?
Nope, whatever streams you give it concat will just wait for the first stream to complete (emitting all its values) and then it will subscribe to the next stream you gave it (emit all those values), and then the next stream and so on. If you just want emissions from any of the streams whenever they emit (rather than being ordered like with concat) then you might want to use something like merge instead.
Share github url