Check out a free preview of the full Advanced Asynchronous JavaScript course
The "Image Viewer Streams" Lesson is part of the full, Advanced Asynchronous JavaScript course featured in this preview video. Here's what you'd learn in this lesson:
With prompting of the students, Jafar starts to define the direction of building the app by looking at the available streams and the ones that are needed to be created.
Transcript from the "Image Viewer Streams" Lesson
[00:00:00]
>> I wanna talk through some possible solutions. So here's the image.js file when it loads up. And here's this getSubImages, which I have just used and here's where the program really starts. At the moment, we have remember we talked about how we do problem solving observables? We take the streams that we have and then we try and figure out how to transform them, like we did in the previous example, into the stream that we want.
[00:00:28]
Before we do that, we have to figure out what are the streams we want? What were the streams I would need for an application like this? The ones that I wanna create, not the ones that I have. In this particular context, I just wanna create a stream of all the images to display, that's all I wanna do.
[00:00:48]
Whenever it fires an image, I'm just gonna display that image in my image done placeholder, and that's all I wanna do. I wanna create a stream of images to display. Now what images come out of that scream is gonna be halfway dependent on, whether the user presses the back button or the next button and which sub image they're on etc.
[00:01:05]
So I basically have to take all those possible inputs of back and next, and sub render it and network response, and I somehow have to co-list them into just one stream of images to display, makes sense? And I'm also going to put in this actions observable. As in whenever the user performs any action, I'm actually just gonna display this loading icon that I have onscreen that's gonna sit right on top of the image.
[00:01:30]
And then once the image is loaded, I'm going to hide that loading icon, is everybody see that? So whenever I display an image I just hide the loading icon, and whenever the user initiates any action at all, I display the loading icon, like so, does that make sense?
[00:01:46]
So our job is to, right now I've just put on a placeholder here for actions and systems Observable.empty. But basically we want actions to fires whenever the users presses left, right, or picks sub. And furthermore, we want images to fire whenever we have a new image to display based on what images are available and what buttons the user clicked, does that make sense?
[00:02:10]
So first of all, what streams do we have to construct images with? So if we look up at the top of our program we have five DOM elements. We have the next, a back, a sub, which is a select box. So the currently selected option in that sub is the thing we wanna pull the data for.
[00:02:32]
And we have image, which is a DOM element where we're gonna display when it changed a source of that image to display the currently visible image. And finally, we have this loading image, which we're just simply gonna hide and show depending on what's going on. So what are the interesting events that make up images?
[00:02:56]
>> Sub selection?.
>> Sub selection, absolutely. Let's create a sub selection. Okay, how am I gonna get the subs that are selected?
>> fromEvent Observable?
>> Yeah, I can use fromEvent. We wrote that earlier, remember? I pass in sub and I think it's just change. But that's gonna give me event objects that happened in the onChange.
[00:03:36]
I do actually want the value inside of the option though. So, how am I going to get it?
>> Map the event.
>> Yeah, I could map the event. Maybe it's target.value, I don't know. Let's try it and find out. So, if I wanna know what an observable is gonna give me, how can I find out what data's inside?
[00:04:04]
>> Subscribe to it.
>> Yeah, subscribe to it. So I'll subscribe to it. I have no idea if it's gonna work but let's try it. Okay, awesome, first try. All right, so did everybody see what I did there. I changed the select box and then my observable fired the new thing that was selected, which in this case is queued.
[00:04:37]
I'll switch back to pics, so, cool. And it's that easy to take the select box and turn it into a stream of all of the future values that will ever be selected inside of that select box. Okay, now we're cooking. So we have a stream of all the subs, what are the other streams we're interested in?
[00:05:00]
>> Next and back buttons?
>> Yeah, the next and back buttons. So we'll notice a little pattern here where I take a singular DOM element. And then I create a plural stream of events off of that DOM element. So I'm going to go to nexts, and, Looks like it's nextButton instead of select.
[00:05:46]
How did that even work? It's actually subSelect, but apparently the browser or anything with an ID it just creates that in the scope. Cuz I put in sub instead of subSelect, but I'm assuming what happened is that the browser anything you give an ID it just places in scope.
[00:06:04]
So that shouldn't have worked, but or I didn't expect it to work but it did. And likewise here I'm gonna put a nextButton and backButton. Cool, any ideas about what to do next? Remember that we're trying to build two streams, the stream of all the images to display, and the stream of all the actions the user performs.
[00:06:29]
When the user performs an action, what do we wanna do immediately to give them feedback so that they that something's happening. Yeah, we want to show a loading image, right? So inside of it we had an actions observable. Do we have everything we need to make the actions observable?
[00:06:56]
All right, when do we wanna display loading? When they switch a sub, when they click next, or when they click back, right? So I think we actually have everything we need right now to create actions. How are we gonna do it?
>> Concatenate the three Observables and then display the loader, subscribe to that and spread the loader.
[00:07:19]
>> So I'll settle this placeholder right now, action's empty, I'm just gonna go subs, Like that? Is that the idea? Who thinks that's the right thing to do?
>> So should we use was it switch all instead of concat for so that they cancelled? It takes the latest or is that?
[00:07:49]
>> Well in this case, so switch latest, merge all, and concat all operate on streams of streams. In this case, we actually just have three streams. And so the only functions available to us are observable.merge and observable.concat, does that make sense?
>> Yeah
>> So who feels like this is the right way of doing it?
[00:08:12]
Of getting-
>> Merge would be better because subs, next, and back aren't going to complete ever.
>> Right, it is generally a bad idea to concatenate infinite streams together. You will never get to the second stream, right? Is that clear to everyone, why I will never ever get to next or backs?
[00:08:30]
It's because concat, which we all know, cuz we implemented it, will only move onto next and backs when it gets a complete from subs. We can solve that problem by using merge, I think that just might be the answer. The actions, we're moving rather quickly here, I'm gonna have to come up with new problems, let's check it out.
[00:08:49]
What should happen is if I change any of these variables we should see loading, cool. By the way, these are public domain images, I'm sorry, they're ugly, but that's the best I could come up with on short notice, so, great. That worked. So we're actually halfway there, if you divide this into two observables, we're actually only like 5% there.
[00:09:11]
The other one's the hard part, so let's tackle that one.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops