Complex Features Made Easy With RxJS - Ben Lesh

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so this is my first time in New York I've never been here before I'm really excited that we had you know New York style pizza over there make it fun it was it was fine it was good so again my name is Ben Lesh I am the lead author of rxjs I am now on the angular core team as of like eight months ago or so I'm not the creator of RCS some people have said that Matt Papa sucky is a guy that created he's actually in New York you worked in New York that created RCS while he was working at Microsoft it's it's pretty much a straight port there was pretty much a straight part of our X dot net and so some of the things that you find today in the version that I work on are still kind of relics from from that past so just let me get over to my set of slides here actually I originally was gonna start off with live coding and observable I think I'm gonna do that for the second part first off and it's again it's gonna be really hard for for me to see but I'm just going to try to rough estimate from like the group in the front that I can actually see through this like how many folks here are actively using arcs yes today a lot of a lot of people so I'm going to assume that there's a general understanding of arcs Jess but I'm gonna I'm gonna try to go over just really quick generally what arcs Jess is and get people excited about it how many people here think RCS suck sir is really difficult you're not gonna hurt my feeling oh you just don't like raising your hands that's fine that's fine my feelings are hurt that you didn't raise your hands so I'm actually gonna start off with adding features to an existing angular app oh this is a talk that maybe you might have seen me do before I'm doing again just because a lot of people have not seen this talk yet I want to get people excited about it and you have an opportunity to ask me questions about it afterwards so loading come on Google there we go all right so complex is made easy with Arceus and easy I should have put in quotation marks because it's easy if you know arts yes if you don't then it's hard I know it's hard again I already went over this so question of like what is arch s comes up a lot in sometimes some people don't even think they know what it is sometimes how are a little off about it so just I want to give a quick primer on what our sis is observables are the main focus of RCS we have these this type called observables and what they are is they're essentially sets of events so they give you zero too many values over time and that can last any amount of time they're cancelable which makes them different from other primitives like say promises and they're lazy which is a key difference between them and promises so when I say lazy like a function is lazy a function does nothing until you actually call the function right observables are the same way they don't do anything until you call subscribe so again they require a subscription if I am an observable some observable and frequently you'll see this dollar sign at the end and so through a lot of my code here you'll see dollar signs on the end of the observable just so you can identify which variables are observables we don't actually do this inside of Google Google has style rules that they don't want this in their script but I am on the fence I don't care one way or the other I think it's helpful for a lot of people but again generally what happens is when you get an observable you subscribe to it and usually people end up subscribe subscribing with one call back and that callback gets called every single time you get a new value from whatever is producing data inside the Israel there's a second callback that you can provide which is the error callback so a weird little-known fact about this is if you provide an error callback ARC's just assumes that you're handling errors if you don't provide it Arceus provides default error handling which just says hey you didn't handle this so I'm going to throw it on a new stack and then you can catch it in like window on error process on Aaron node and then there's a final call which generally it doesn't get used a lot in application code but it gets used a lot inside of rxjs the library which is this isn't this is a completion callback so this says hey I'm done producing values I'm no longer giving them to you this is kind of the end of your your set of values over time gives you the ability to cancel so when you subscribe you get this subscription back which is a this cancellation semantics and later on you can call unsubscribe on it which is your code saying hey I no longer care about the values you're sending to me please stop and that signals some teardown under the hood which is an actual solid benefit of ours but the most important thing to know is observables push values you subscribe to them and they push values over time and I keep talking about other collections or sets of things the reason that this is key is it enables us to do some really interesting stuff we have operations you can perform on sets of things and this is just a universal truth about like it's a truth of the universe right if I if I have a set of apples I can made it make a set of apple pies well I'd need more sets of other things I can combine those sets and make a set of apple pies right if I have an array of numbers I can transform that with map into an array of strings if I want or an array of other numbers so there's transformations you can you can widdle your array of numbers down to smaller things you can do the same thing with apples or observables or whatever if you have a set of things you can filter them you can transform them you can combine them in different ways you can run accumulations on them like a like a reducer or that sort of thing just just if you walk away with nothing if you walk away and say uh rxjs still sucks that's fine but this is true about sets of things no matter where you are in life even if you're not programming so it's it's something to know flattening by the way is the act of say if you have an array of arrays you can flatten it to a single array you can do that with sets of things as well at least with most sets of things provided they have the right properties and observables you can flatten an observable of observables into a single observable of values so again laser collections you can do this with a raise I've got you've got filter map and reduce exist on native arrays some people don't know this but you can take an array of numbers you can filter it and say give me all the numbers that are greater than four double them and then sum them with you that's what reduce is doing at the bottom observables you can do exactly the same thing so I can say from that same array and then pipe it through our operators from our CIS and there they've got the same names they do exactly the same thing the only difference is you have to subscribe to it because it returns an observable and observables don't do anything unless you subscribe so there they also unlike arrays they have this element of time right so there's different operations you can perform on on an observable that you couldn't really perform on an array for example you can debounce them right like so you can say I have an observable and I want to make a new observable that only emits values that have come through with this the specified kind of time period to to keep it from spamming me too much you can throttle it's the same sort of idea you can delay the values from getting to you you can race to observables against each other and whichever one emits first wins and you kill the other one and keep that one there's a variety of things there's a lot of different things and that's one of the reasons why when you go and you look at the RCS API you're like oh my god there's 60 plus operators here what do I use it's because there's a lot more things you can do with this primitive so an example of something you might do with RCS you can do a basic drag-and-drop so this is just saying give me an observable of mouse downs and whenever there's a mouse down event I want to map that into all the mouse move events but only take those until there's a mouse up event so exhaust map is this operator that just says hey map to this new observable and give me all the values of it until it completes and I don't care if you if another value comes in and you try to map to new observable it's like the opposite of switch map if you're familiar with switch mapping arcs yes so say button you can't double submit this is a this has been an ongoing thing for pretty much as long as I've been doing web development you don't want somebody submitting their credit card information twice or adding multiple records so people like gray out the submit button or whatever you could just use rx to do something like that so the same with exaust map you just say every time click Save I want you to post the data but I'm using exhaust map so every other click to save just gets dropped and tell that that posted data comes back so that's another use case for this operator the throttle daughter would suggest this is a this isn't like the idiomatic example that people do in our SES all the time so you take text input changes so every time the value changes in an input and we're saying debounce it by half I'm sorry demands about half of a second so what it's going to do is it's going to say oh if you if you type a bunch of keys within a half second of the last key press I want you to ignore all that wait for a half a second and if you haven't hit anything else then take the value and go on to the next step which is going to do our get to get our search data wait for it to come back and give us the results so this I mean it does it all in roughly a line or two of code depending on how you format it but writing this it would just with imperative code is actually non-trivial use that's something like a load - to help you I suppose so the real thing that you want to use our shifts for you can use it for a lot of things because I showed that you can iterate over arrays synchronously and do other stuff with arcs yes but the real thing that it's made for is kind of composing asynchronous so you've got this set of operations you can perform on asynchronous things which means you can kind of query events like a database if you want so and combine different sets of events that sort of thing so composing events together asynchronous things is really what rxjs is made for Arceus can be used everywhere I have personally used RCS in every one of these things except or view well that's not even true I helped the view community with their with their ArcGIS helper library but yeah it's it's if you use slack if you use a Playstation 4 if you use a smart TV which has Netflix on it like your rxjs is running somewhere in that so it can it can run on pretty much any runtime it's not just for angular but this this is obviously any other meetup in this talk is about doing some stuff in angular so I was just talking about how observant and you end up having to kind of manage that subscription object when it comes back so you can call unsubscribe later otherwise you could end up with some weird memory leaks but in angular we have this pipe async helper and pipe async is is very useful because what it does is it subscribes to the observable for you takes the values that are emitted and then binds them out to the view in this one spot and an interesting thing about this is if you show or hide that spot in the template when it's shown it's going to subscribe and when you hide it it's going to unsubscribe for you same thing with when the component is is initializer when it's destroyed it automatically will subscribe and unsubscribe if you've got this pipe a sink in there but that causes subscription via the same mechanism kind of under the hood I have a nice basic stalk if you want to watch a much fatter version of me talk about RCS that I will send out the slides later on Twitter but this kind of goes over basic error handling and some other interesting stuff but here's the admin update it's the world's greatest newsfeed app right it's just a list of just a list of data that I'm getting that's randomly generated and it just just displayed to a screen like it's it's it's a fake newsfeed essentially what we want to do is we want to add an auto refresh feature to it so just after a delay we want to add we want to have it automatically refresh the data and then more interestingly you want to add like a drag down to reload right so people have the Refresh things like you see it in browsers sometimes where you see it in like native apps so if you if you were to have like a PWA or something like that with this with this angular and you really want to be able to do the drag down to refresh you need to have you need to coordinate some kind of interesting things to get this done so I'm going to show that later it's interesting because there's animations and there's loading and user interaction that sort of thing you have to compose them together so the basics about existing app is just two things we've got a new speed service and we've got a latest news component it's the simplest angular app that I could see even and still update so our latest news component looks like this we've we've got our our news we're injecting our new service feed or our new speed service rather and we also have an existing property on there which is the observable of like the news feed values this this observable when you call it we'll go get them the news feed data and bring it back and resolve and you get it so I'll show that in just a second so again just to focus on this this is the important part that just to get rid of the imports at the top we've got our news dollar sign property which we're gonna bind out to the view here so our ng 4 you see I'm doing a pipe async on our news dollar sign property what that's gonna do is subscribe to that news that news property and every time it emits a value which is an array of news it's going to loop over it with ng 4 and then bind the data out to the view which has the title and the timestamp and some other things our news feed service is pretty dead simple it's just a class with a property on it I could I could inject the property directly with like a token I think it just kind of muddied up the example so I chose to put it on a property of this class but it's the property is an observable and the reason the property is an observable not a function that returns an observable is because observables are essentially functions they don't do anything until you subscribe to them so wrapping this in a function with no arguments would just be like having a function that returned to function with no arguments it doesn't make any sense so it's just a property and every time you subscribe to that observable what it's going to do is it's going to use angular HTTP client to get the new speed do a little bit of mapping this code this code is kind of bold actually and then it has some air handling in here in there and in this case the error handling just has a side effect of logging to console here you might actually display something to the user or something that would be a feature you could add with a side effect but it's returning empty which is just an observable of nothing we're just kind of saying hey I've handled this you don't need to do anything else continue on and we what we're also sharing and this is important because that means everyone that subscribes to this news observable with like as it's out and in doing its thing will share the the underlying request so you don't make multiple requests every time someone subscribes to it so again it's just a basic news feed that was the entire app I just explained it in a few minutes but we need to add we need to add the update interval feature so we're gonna I'm going to start off by refactoring the newsfeed service a bit because right now it's pretty simple all that happens when you subscribe to news is you just get this observable basically like a an already initialized get get observable that is doing some other stuff it's we're gonna go yeah so what I want to do to update this is I'm going to go and I'm going to say alright instead of news being are going directly to HTTP client get I'm gonna have news come from refresh which is a behavior subject now subjects are this thing inside of Arc's yes or you can call next on it and it causes the subject which is an observable itself to emit a value and what I'm going to do is I'm gonna say what what is this news dollar sign which is H if you get is a property called load news and every single time someone calls next in to refresh I'm going to map that into load news and subscribe to it and wait for that to come back I don't expect everyone to follow this again I'm just I'm just doing this to kind of show some of the powerful things you can do with arcs yes so and then on on this side what we need to do is we're gonna add a refresh timer in fact if we did nothing right now the app still works the way it did what we want to add a refresh timer and the reason the app still works the way it did is a behavior subject when you first subscribe to it gives you like an initial emission of some value so that causes the news the the news feed to originally load but if I add a refresh timer here which I'm doing with timer which is a helper function that comes from RCS its timer what it does is it says if you give it zero and then a second numeric argument it says omit the first value at zero milliseconds and then have an interval every 30 in this case 30 seconds that's gonna emit a new value so it's 0 and then 1 and then 2 and so on we don't really care too much about the actual numbers that come out of the timer but we're gonna use the the Refresh timer to force the new speed to refresh and in order to do this I'm actually gonna have to manually subscribe in this case so I'm going to at least in this particular implementation that's what I'm doing so I'm going to say I'm going to add on in it and I'm gonna say when the PO the component mounts was so on in it I'm going to subscribe to the Refresh timer and pump the value straight into refresh which is our behavior subject so every time refresh timer emits refresh is going to get notified of like hey go go do this and then refresh triggers load news and then we get our news data so this is all I really needed to do to update that the other thing that I want to do too is I you see I've captured the subscription I don't want that timer to keep going forever after my component is destroyed I need to I need to clean that up so I've captured my subscription and a property I need to add the property to make typescript happy and then I add an NG ondestroy at the bottom that has the on the unsubscribe in it right so when the component unmount s-- or when it's destroyed we're going to call unsubscribe on the subscription and stop the timer so that's the whole thing in a nutshell so just to recap before I sure working because I've got a little video of it working we use a behavior subject to kind of reactively trigger the the reload so now if we have our news feed service and we call next on that refresh it's going to tell whoever subscribed to that news observable that they're gonna get new news at whenever it comes back our latest news component we added a timer to it and we next it into that behavior subject and then we also had to manage our subscription with on an it and on destroy if anybody here uses react or ember or another framework say like in react you would use instead of uninit non destroy it would be component did mount in component will unmount it's the same exact um it's like did mount and will and mount an ember it's the same exact sort of mechanism it works the same across any framework so now I've got this I change it to three seconds so now I've got this thing is it playing yes and it it refreshes every three seconds or so so that was that was the whole feature I wanted I would change it to like 30 seconds or something later or a minute or something that wasn't so spammy but that's the basic idea so you might notice we didn't touch the template the entire time I did that the refactor was pretty small even though it took a while to explain and what we really kind of did is we worked backwards so I started with saying you know hey I I need to I have this this HTTP thing that's like the minimal thing I need to make something else that kind of feeds into it to that in order to get that to update on demand and then I need something to feed into that and so on so I've kind of worked my way backwards to the chain it's harder to see in this example because we didn't do as much but we're gonna see it more in the pulldown to reload feature so the reason that this is a the example I chose is because it's got a lot of stuff to coordinate it's not a feature that most people would ever need to add it's not even maybe a good feature to add I don't know but it's a feature that has a lot of things to coordinate you have to deal with user touch events right so you start when the user touches you track their download pull with some sort of icon right so you have to move the icon when they're pulling down and you want to have the icon start spinning if they get past a certain point and trigger a reload and then when the reloads done which has nothing to do with what their fingers doing you want to animate that thing back up to where it was but not have what their fingers doing interfere with that right if they don't pull it down far enough and they let go it's got to animate back up to where it was so there's the a lot of stuff to kind of coordinate with this and that and you also have the animation which itself could be in observable you can make animations with the observable I actually did in this example but I don't dive into animations because that would be a whole separate you know 30 minute talk probably of how to make animations with Rx but so again there's just a lot to coordinate there's three different touch events there's Ajax that we have to know when it starts and when it completes and you also have to deal with animations and you have to kind of get all these things working together so I'm going to do this by creating a few things I'm going to add a touch drag to load component and this is going to be responsible for controlling that drag icon that's gonna follow my finger it has to admit some events also it's gonna have to say hey it's been i want to reload because I've gone past this this particular point it's got a deal with coordinating all those touch events and animating that that icon I also will end up needing to refactor the latest news component because I need to include that new touch drag to load component and then I also need to I need to wire up the event to next into the nude speed nudes newsfeed service to get getting who values in there that was a horrible slip of the tongue sorry about that so our test dragged the load component just to start off I've added an output here for the Refresh events so this is going to be winning when you drag past a certain point we're gonna send an event out of this event emitter so whoever's consuming it knows hey someone's past a certain point and I need to do a thing the actual HTML and this is just straight HTML at this point I'm not doing anything dynamic looks like this I've got an outer div to kind of deal with centering the stuff I've got an inner div which I'm actually going to dynamically change that it's stealing with moving moving that the icon down in a vertical manner I've got an SVG which I've got a transform on that I'm gonna change dynamically to rotate the the icon and then I've got the actual icon as a pair of circles that are one's kind of off-center from the other so you can see that it's spinning I've got my latest news component here I'm gonna need to add that touch drag to refresh and all I'm gonna do is I'm literally just gonna have this refresh event next into newsfeed service refresh I could have it call back to a method it might make it more testable but for a sake of simplicity for this example I'm just saying every time I get a refresh event from this component I'll call next on refresh and we know that triggers the the newsfeed data to reload which is already bound to our component here so now we can see it just kind of sitting there and things will read be refreshing in the background but that doesn't do anything it's just like here's a circle congratulations so we need to we need to kind of let's get this thing kind of like animating or moving first I'm gonna make this whole thing dynamic so I'm taking the same HTML and I'm saying okay well I'm going to dynamically change style transform on that inner div with this transform positions observable right so I'm subscribed to observable called transform positions that I'm gonna get that that string from and put it in there same thing with the transform on the SVG only I'm calling it transform rotate so this is gonna get that rotation string and then on the component I add these the simplest possible observable I can I can add to make it work so it's just an observable of the exact same strings I just pulled out of the HTML right cuz I'm working my way backwards I'm gonna totally replace these in a bit but right now I just want to make sure it works so I put that in there and it should be fine however I know that I want to deal with numbers and not strings because I'm gonna do some manipulation of where it's at so I'm gonna make transform positions derive from another property called positions which is now just an observable of 0 the simplest possible thing and it's going to map that 0 into the string that we had there before right so it's saying here's a 0 now a 0 equals translate3d negative 30 5px 0px the negative 35 PX by the way is because our circle is 70 pixels in height that's kind of offsetting it and then i'm gonna do the same thing for transform rotate I'm going to have it derived from an observable of number also a simplest possible thing is a durable of zero and then if I look at it it looks exactly the same not exciting but this is being dynamically produced at this point from from an observable so I'm gonna I'm gonna add a slight tweak to this so we can move the marker off the screen again that marker is 70 pixels in diameter so just to shove it off we subtract 70 from the Y position it's off the top and now let's make touch drags affect the position earlier I showed mouse downs so the I'm sorry the the mouse version of like drag and drop right so it's again Mouse downs and for every Mouse down you map that into an observable of all mouse movements but you take those Intel Mouse up and you subscribe to that so this is ends up being an observable of mouse movement events it only happens while your yours on there or in this case when your mouse is clicked so we're gonna do the same thing only with touch and I'm gonna use Rx Jessa's helper from event for this because I care about the events in the entire document there are ways to hook this in angular I think this is more straightforward you can do it however you like but at the end of the day this each one of these from event document touch start that just makes an observable of touch start events or observable of touch movie events or an observable touch end events and the pattern is exactly the same for every touch start give me all the touch moves and take those until they're until a touch end of it right and this is a really weird of entry you might have to do other things with touch because you can touch more than once if you look at this example and you try to use it directly this is kind of just a basic example so it's not to know people's heads about those sorts of things but oryx can handle that too and then I'm just gonna take that and I'm gonna add that directly to my touch regular component so now I've got these four new properties I've got touchstart touchmove and touch end touch end should probably be capitalized on the one line and then I've got this touch drags which is derived from those others and again every one of these things is just an observable we're gonna need to subscribe to them to make them doing and remember before I had this positions of durable that was just an observable of zero I'm going to make that now come straight from touch drags and so touch drugs though we need it to be an observable like Y position so an observable of number and right now it's an observable of an observable of touch events right so that those aren't numbers so in order to get that what I'm gonna do is I'm going to add a map into the into the touch move step and basically I'm gonna say for every I'm just looking at the first touch in this case wherever the whatever the Y position is for the current touch movement I'm going to subtract the Y position for whatever I started from the touchstart event all right so I get like a diff of like how far down I've drugged and just just to focus on that a little bit I took some this stuff off the outside oh the other thing I did is you'll you'll see down at the bottom I'm adding a start with on positions because I want to start at zero and I'm not starting with anything if I'm waiting for a touch event right so I wanted to start at zero so it starts off the screen so now if I do this it moves with touch doesn't do anything else but movements exciting right I I personally get a kick out of doing anything that involves animation or like moving things because so often you're just like I've got data in a database now I've got data on a screen I'm putting data back in the database you don't get to do any of the fun stuff right so let's make it animate home when we let go I have an arc seus animations talk that I gave again it's a whole talk I really want to do any more than two talks today so there's a there's a video this with a thinner me that is dressed very fancy talking about how I do our animations the long story short animations are basically you take an observable of animation frames and then math and then you get this every animation frame you get a diff like a number change over over a certain duration so it's it's a fun talk I like to I like doing that one in particular because animations are so they're really really the short short version is that I have this animation service that has an interface that looks like this it's got a tween method on it that takes a number that you want to start with and a number you want to end on and a duration and it triggers a bunch of animation frames and the first value it emits is the start number and then over the duration it does some math to figure out how far into your duration it is and it gives you values between the start and the end number everyone can get that so back to this what I need to do is I'm going to focus on altering touch drags now because I know that's feeding into my positions and I'm gonna say alright I'm adding this new property called move home cuz I'm going to probably have to use this more than once and this is just saying use the animation service tween from some position that I'm storing in state some people will say this isn't the purest version of our X ever I don't care if it's readable and it's maintainable fine I can see there's a private member named underscore POS there that's that's fine that's what we're gonna use so from whatever POS is to 0 and 0.2 seconds that's that's our animation is just numbers that we're getting so so probe show from POS to 0 and then what I'm gonna do is I'm just gonna say hey take the mouse movements and whenever mouse movements has done so it's because we're taking that until touch in so whenever the touch is over I'm going to add move home right after it with kin cat so I'm gonna concatenate the move home observable to the two right after the amount of the touch movements observable is done and it's only done when I when I let go with touch right so as soon as I let go it's gonna it's gonna play this move home animation and that those numbers are gonna feed out of touch drags exactly the same but there is one weird problem POS is always zero right so we need to do something to update that so there's this there's a side effect operator called tap and that just says hey whatever number you have right here I want you to set underscore POS with it it's just kind of tap into what value is in the observable at that point and has the side effect of updating underscore POS but there's one more weird problem which is whenever move home is created which happens when you construct the observable us is always zero so your animation your tween will always be between zero and zero always every time you subscribe to it so I need to I need to delay the creation of that animations tween and Arceus has a helper method for this called defer and what the FIR is is to fir just says here's a function that when you subscribe to the observable you get back from defer I want you to execute this function and subscribe to whatever observable is it returns so it's just deferring the creation of an observable so it's a later on so now this this should work just fine so when I drag down and I and I lift it animates back which I mean that's exciting now it's doing things on its own right it's not always good with your code when it does things on its own but in this case it's good so let's make it refresh the feed if you get far enough so we've got it animating back we've got it following your finger but if you drag far enough we want it to enemy back so I'm gonna go back and look at our touch drags and I'm gonna add something to touch rags which is after the exhaust map I'm gonna add another tap and really because this this is another place for a side effect because I want to I want to emit an event from my refresh event on this component right which we already wired up to refresh on our on our news service in our other template and that's gonna go trigger the data reload so this is just saying hey if Y gets past half the inner height of the window then I want you to call emit and it's for every single value of y that makes it that far right so if I dragon them all over here it's gonna it's gonna emit a whole bunch of times we don't want that so I'm gonna add one more thing which is take while you only we only want to take the values until they get past the the window enter height if you get past that then this whole observable now gonna stop the entire thing which means our drag stuff isn't gonna work anymore too but we can watch let's see so there's a first dragon animates back the second drag I pull it down and it does refresh the data which is exciting but then the touch doesn't work anymore cuz I've killed the entire observable with that take while at the end so what do we do oh my gosh well I'll tell you right well I think I do that next right right now let's just have a go go home after the load is finished we'll complete the entire load segment first so I got ahead of myself there I was excited so what I'm gonna focus on now is I'm going to focus on this this positions thing and I need to update positions now with an additional animation that only occurs when the news feed gets gets its new data back so I'm gonna have this property called move home after load and basically I'm just gonna say hey every time load news resolves on my news feed service I want to map that into move home and play it till that play that til it's done all right because that already exists news feed service load news is a shared observable of that there's HTTP results when they when they come back and then I'm going to make positions come from position updates now instead of just touch drags so that's just gonna concoct a take all the test drags until it ends and then as soon as it ends let's move home after those look so it's gonna play that animation right afterwards and then I just changed this to come from position updates instead of touch drags of the positions day so now now we get to where it loads the data in and animates back but it only works one time and it's you can't drag it anymore because that whole the whole observable chain has died because it played through the take while and then we played through the animation and that's it because that's the that's the end of the concoction-- right so this is actually a really easy fix what we do is we just added repeat on the end of our catenation there and now what that does is say hey do this test drag thing until you get past you drag past half the distance of the the height of the window and then play the home atom then what to play the home animation until the data comes back right and then you're done but wait repeat okay go up and do the test drag thing again so just research grants of that and it waits for that to be done and then it moves on to the move home after reload so now it works and it goes back but as the text says it's boring if it doesn't spin it's my opinion I think it's boring when it doesn't spin so let's make it spin we have this we've kind of forgotten about this so far we have this property of just a rotate of zero that's obviously what we're gonna be messing with probably not the transform one underneath it's just the string manipulation part so what I'm gonna do is I'm gonna use my tween again I'm gonna say hey let's make this tween between 0 and 360 so for those of you that have forgotten geometry or trigger whatever that's 60 degrees all the way around a circle and that's gonna make a go around once in half a second and to make it continuously go around we decided our friend repeat again which are already using elsewhere so now if you subscribe to this and you were to pump those values through this rotate here it's going to well it's already going through rotate if you were to subscribe to this it's just gonna spin continuously and since we've already subscribed to it in the in the template now when you pull it down it's always spinning like always which I don't know maybe you want that picture kind of cool so but we really want to restrict the spinning to only while the data is loading so what I'm gonna do there is I'm gonna change this a bit and I'm gonna say hey every single time that news feed refresh gets a value next it into it this is the same subject that I'm using to trigger my reloads right so every time someone calls next on refresh which says hey go start go start loading the data I'm also going to trigger the animation and then I'm going to take that until the data comes back from load news but I want to end with zero so it doesn't end up in some weird cockeyed position right like we want to put it back to where it belongs let's see that's it that's our entire feature we've got our drag down to reload follows your finger it spins it's all fun your team is gonna be so happy when you add this feature so the important thing is I talked a lot about all this but really this entire behavior that we added was like about 50 lines of code right you can do this too in parrot with imperative code good luck getting it that's so what the trade-off here is obviously things around readability there's ways to improve that that I didn't do mostly for the simplicity of just showing the using of the operators here but at the end of the day you know you're you're shipping a lot less code it's code that's being reused most of this stuff is is used in other parts of angular like in the router and those sorts of things so it's not adding a lot of size to your bundle and you have this a pretty cool feature for not a lot of additional coding on your part so again the summary for this talk is that arc CS is really best at coordinating events so you can use it for a lot of other interesting things you want to work your way backwards so start like find something out to your view start with the minimal observable that like will make your view look right and then go through and figure out okay well what other observables or I need to feed into that one and how do I transform those into the right shape so a lot of ArcGIS is about scrubbing data in observables to the shape that you need and if you ever need to create an observable dynamically like so you add some property and you're like oh crap this there's this weird thing happening where I create an observable and I value for it doesn't exist until after the component mounts or something you can wrap it into fur and voila magic it works defers a pretty small bit of code actually - there's this pattern would take while and repeat so sometimes you'll build a whole durable chain out and it'll be like oh I got this thing coordinating all the things we want but I had to do this take while at the end and the whole thing dies after to take while and what do I do and a lot of people don't realize you just add repeat and it starts the whole process over again so it's that's an interesting pattern and then the other thing you want to do that I did through this and I didn't really talk about it too much as you try to factor out your observables into other properties on your component because it will make it easier to test in some cases and in angular you might even want to move some of them off to their own services and stuff so you can inject them but that's it in a nutshell so again the demo repo actually exists for this you can go out and look at it all in these slides out you can follow me on Twitter I answer just I think I've successfully answered every question anyone's ever sent me on Twitter but it does take me a while so and this is Barry's I get questions all the way from how do I become a good developer and it's like to see you you know more more specific questions about Arceus or angular ok so the question was he's using a UI router I'm just saying this four people are streaming he's using UI router so angular 1 right angular 2 UI router um I haven't played with that too much but if you have a promise if from any any library and and you need to convert it to an observable there's a lot of things about ArcGIS where you can take pretty much and I'm going to bring up stack blitz here but you can take pretty much any promise or any operator that accepts an observable and you can just return a promise in there and it'll just work if you need to convert it straight up to an observable you can use from so like if I wanted people everyone can see this or not is it big enough maybe sure so I bring in a from event pattern from and I've got some promise up above here right I can literally just take this and say [Music] it'll work you can't get high out of that so converting it converting a promise to an observable is just as simple as using from from you can you also use to convert arrays iterables anything that it can any set that can be converted to an observable now another thing that people don't realize is if I've got say like like a merge map or something in here and I'm going from of 1 2 3 type merge map and then I've got this promise in there I can I can just as easily return the promise again right typos but and you see it it you get all three results for the promise out of there so any pretty much any API inside of ArcGIS where you can return an observable you can also return a promise or an array or an iterable having having worked on this mostly outside of work as an unpaid volunteer for the last three years I I can tell you that part of my pay for being an open source contributors hearing people complain about the library and how much it sucks although the complaints usually are that it's very complicated or they don't understand it that sort of thing or it's harder to read a lot of the readability just comes from understanding so a thing - oh what one thing that people need to realize is all of these operators are really like a domain-specific language for dealing with sets of events right there's just like learning you know what left join and right join and whatever mean and sequel it's the same thing as you know learning what switch map and merge map and not that those are the same exact idea but you get the idea there it's it's a specific vernacular around dealing with sets of events and people when confronted with are suggests they think well this is JavaScript and I know JavaScript therefore I should know every word that's on my screen and what it means and it's just not true you end up needing to learn a bit about how our sheis works in order to kind of understand at least learn some of those those common pieces I think that the documentation needs a lot of work and there is a lot of work being done around that right now but you know it's all mostly volunteer work so it moves pretty slow but that's the the primary complaints are usually around documentation and complexity not very many complaints about size not very many complaints about speed usually it's just the complexity side of it the other thing to do to know too is if you have RCS and you're just starting using it you don't need to use all the operators like you don't you can just subscribe to it get values out and then do whatever you were normally going to do with it there's literally nothing wrong with that and you can you know build your understanding as you go along it's it's so you don't need to dive in and know all sixty operators I couldn't name them all right now if I had to and I wrote almost all of them so there's I think that with the docs we what we really need to do is kind of get a set of operators that are like the most common ones that people end up using I know that there's already blogs that have done some of these things so but you know just kind of start simple and build your way up not that that's your problem that's just what people say there's also the flip side - sorry there's the flip side where some of Oh get someone on their team who gets really excited about arcs yes because it is kind of like everything's the same shape like Legos and I can put things together and it's so great and so they'll get some one other team that's just like I'm gonna rx everything and then everyone else the team is like I hate the codebase that we work on I don't understand it anymore I hate this other teammate and that Ben Lesh guys sucks so that that happens - I've heard that so please know rxjs all the things until your so your team understands it at least so the question just to repeat it for people that are streaming was about the tc39 proposal for observables it's stuck in limbo it's still it's stage one it doesn't currently have a champion John Hussein is a good friend of mine that I worked with in Netflix no longer works at Netflix and therefore is no longer championing the observable proposal so it's it's kind of sitting there without a champion right now I just talked to Miles borns about that earlier today and someone might pick it up it just depends on bandwidth but it's definitely something where the tc39 needs to they need to either have someone drive at home and decide they don't want to do it or you know whatever but the the decision needs to be made on it there's also a what wig proposal to add to add observables to the Dom in basically anywhere there'd be an event target which is anything with add event listener remove abet listener there would be an on method that where you could say like on click and you get back an observable of click events sort of thing so there's there was some site excitement around that the chrome team really liked it but we would need one more implementer to-- to want to adopt it and again it's a bandwidth thing so there's there's not enough manpower to kind of champion that some of those things that go through well that's the story the story is it's uh it's it's stalled it's stuck in the mud not forgotten definitely the inverse between pipe and map okay so pipe is this kooky function I'm gonna kind of go over that in my next talk but basically pipe is a is a functional thing that says hey you can pass these functional operators to it and it's going to apply those operators to the observable in order so map is an operator so map is this function that returns a function that then gets piped over the observable so you it takes the observable passes it to the result of map and then pass it to the result of the next thing under pipe and the next thing either pipe and so on and you end up with a new observable so so map is an operator pipe is a method on as long as your code is readable and maintainable and it works you're not doing anything wrong period it's beginning the end of the story with all programming for all all time now as far as like the primary use case for subjects when this whole system was designed it's for multi casting so you you get this you get like the observer pattern which is a pattern from the you know the Gang of Four books or whatever and it has an observer and a subject and what the subject is responsible for is it's got an ADD observer and remove observer method on it and then it's got like a notify method that notifies the observers that you've added or removed from it so the subject Rx is no different and what he does is when you subscribe with functions or an observer it scrubs it to observer puts in an internal list and then when you next on it or air on it or complete on it broadcasts that to all the observables observe observer is in its internal list so it's it's of course also an observer on the other side it has the same shape so you can use it to subscribe to an observable so the use case with it is you've taken observable you subscribe to it with a subject and then everyone that subscribes to the subject gets all the values from that observable but only one subscription to that observable so that's that's the general use cases for multi casting however the other use case for it is in situations like oh I need to get a value from a click event or from an event in a template and you don't really have like oh I can go wrap this with from event or something like that to make an observable out of it I think that in the not-so-distant future after Ivy's done with angular you're going to see more features added to angular around creating observables cold observables for user events instead of having to pump them through subjects so things like that are going to be very helpful and you're gonna see fewer subjects show up in your code but at the end of the day I mean if you use a behavior subject like I did here if you use a behavior subject for something I mean in all honesty it's not that bad I think that's in the academic sense like which a lot of a lot of the stuff that was written about arcs j-just before I was ever involved this very academic in the academic sense you know you're not really supposed to do that you're also not supposed to have side effects that right things to underscore POS and that sort of thing but guess what the codes way more readable when I do that and it works so again it's about it's about what what works for you what's readable what's maintainable don't feel guilty in this case I wanted that initial value but I didn't care what the values are because I'm not next thing anything in particular through it so I just put a null in there so here I wanted the behavior subject because I wanted an initial value and replay said it doesn't have an initial value and I would have had to next into the replay subject as soon as the component something to get it to work so yeah it's there's nothing like super bad about that I could have next did something more useful but null seemed fine why allocate anything I don't have to other than a pointer all right so if I was going to do something other than set that that variable on the side I would probably end up using some sort of scan or merge scan and scan the scan operators have internal state that every time you admit it you map into new state it emits the new state and then it stores it right so you didn't abusing something like that in this particular case I played at that and I thought it made the code a little bit too confusing for the talk so but yeah generally speaking when you need to manage state with rx you do scan there's other fancier ones like merge scan and that sort of thing but scan is the the main go see it's effectively it works kind of like a Redux style store one of the things about trying to keep everything rxe and keep everything pure and keep everything contained within these streams it's not like in limit side effects to where you absolutely need them is it generally side effects or shared state is the source of most bugs in software it really is because like more than one process can write to the thing and then in this case I could clearly see in a relatively small component that only one thing was was writing to it if you find yourself writing code where all of a sudden multiple things were writing to underscore POS you should refactor that you shouldn't because you know here it was very obvious what was happening but as soon as you get multiple things writing to underscore piya even if it's two things then it's no longer obvious what what's going on with that so there's a good question
Info
Channel: AngularNYC
Views: 8,580
Rating: undefined out of 5
Keywords: Ben Lesh, RxJS, BehaviorSubject, Observable, touch events
Id: E3Eego8xKdk
Channel Id: undefined
Length: 54min 46sec (3286 seconds)
Published: Fri Dec 07 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.