Video details

State of RxJS | Ben Lesh | ng-conf: Hardwired


Ben Lesh

Get ALL the ng-conf: Hardwired videos for FREE at
ng-conf is a three-day Angular conference focused on delivering the highest quality training in the Angular JavaScript framework. 1500+ developers from across the globe converge on Salt Lake City, UT every year to attend talks and workshops by the Angular team and community experts.
Follow us on twitter Official Website:


So unfortunately, my friend Tracy, she can't be with us today. She is she originally she was going to do this talk and she asked me to help and then she had to pull out entirely for personal reasons. But on her behalf, I do have a Bob Ross finger puppet, which is right here. It's probably the best investment ever made. There are no broken promises. Only observables waiting to happen. So, yeah, that's enough weirdness from my house. But I have that on my desk all the time. It's super important to me. All right. So I want to talk a little bit about the state of our express. Again, my name is Ben Lesh. I'm currently a senior engineer at Citadel Securities. I am also the lead on the ARC's Yes project, and I am formerly of the angular team, as many of you know. So it's it's good to be back and become one of these weird circumstances. So I want to talk a little bit or just really briefly, I want to prefect's this with what our goals are with our access as the ARC's just core teams goals. And really we're a utility library. So we get associated a lot with ANGULAR, but I use it in react projects. I use it and node, we use it all over the place. I've seen it used all over the place. So our goals are really around trying to be a stable and dependable with our releases and trying to break folks. Having smooth updates between releases. We want to improve your developer experience as time goes on and we want to try to make our access smaller and faster to improve user experience without ideally without even knowing as you update over time. So let's start off with a little news. So the news around this is around the community. We've got for one thing, our share is growing a lot. So we've got about 18 million, more than 18 million downloads a week now, which is up from eight million at this time last year. And that's that's a lot. And that's NPM downloads, though. So you can take that with a grain of salt because you could write a bot that that did that if you wanted. But it's I mean, it's a fairly organic line, except that we're different, some revenue in app on there. But it's it's showing growth. And there's a lot of other signs of the communities growing as well. I also want to take the time to welcome our newest core team member who's Moesha. And I think I'd butchered his last name and it might have been an extra in there I'm sorry, Moesha, but I met Moesha at Google. He was one of the gigglers that helped me start it. Kind of a task force inside of Google to make sure that our just distinct inside of Google, he's now at Bloomberg and he's doing some amazing stuff with TypeScript. He's got some really interesting ideas for things we can do. And ARC's, just to make your experience better, so I'm really, really happy to have him aboard. Very smart guy. Another thing that happened in the last year, just just this last September, is we had our first ever all our express conference, which was amazing. It was a smaller conference, but it was run by prosti and friends. And it happened in Vegas. There are some really great videos, unfortunately, that because of a technical gaffe, they did it all of the videos. But you can when I get this out, you can go to the YouTube link. And watching the video, some of the best talks actually bar none, the best talks I've ever seen on our express and a collection where we're at. So I think the last thing that folks heard as I was talking about our exchanges live Vegas, just so you're aware, this is a this was a great, great conference that happened last September put on by Frosti and other folks that you probably know. It was a smaller conference, but some of the best talks I've ever seen, actually all of the best talks I've ever seen in our shows where we're at this conference and a lot of them are recorded, some of them didn't make it through because of technical difficulties with recordings. But you can find those on YouTube and I'll make sure to get these slides out so I can get that link. There is another hour. She is live coming up in September. It was supposed to be a few weeks ago, but because of current events, it didn't happen. So it's going to be coming up in September. Hopefully we can do it on site. If not, maybe it'll have to be remote or something like that because of, again, current events. So hopefully the world straightened itself out or that we'll see that you can find out more information about that. ARC's just gottleib. So let's let's talk about what's new in version seven, so version seven is that I skipped something. Oh, my gosh, it skipped the most important thing. So this this is the biggest thing that's happened is this week our seven went to Beta. It's been an alpha for a long time. You can still install it from ARC's just at next. And it's at seven. Oh, a bit of zero right now. Probably a better one pretty quickly because there's a few things that we want to fix in there. But again, it's in beta. It's it's pretty stable and it's got a lot of good stuff in it. I'm going to tell you about here, Charlie. That's jumping of some sort. All right. So what's new in seven? So this is what's new in the beta list we've got. And trustability. And what I mean by that is we have a process in place now to try to make sure that we don't have any. It is between patch releases. I'll talk about that shortly. We have better types, care, support. So trying to add four types for you. Much better. And we're trying to use the latest features of typescript three. We've got some new functionality that's exciting that I'm happy to tell you about. And deputations, lots of deprecation things. But there are things that's been built up over time and we haven't removed anything yet because we don't want people to break because we removed an API and we've got a plan for that over the course of version seven. So I'm going to talk about that when I talk about what's going to happen, version seven, one and beyond. All right. It said it's really jumping on sides. I don't know why. All right. So I want to talk about troops stability. So with improved stability, what I'm talking about is we are working with we're partnering with Google. So as a lot of you know, I used to work at Google. When I left Google, there was some concern about whether or not Google would be able to keep our access up to date internally. And they were. And it was to the point where they were worried they were going to have to fork our chests or something like that. There's no reason there hasn't ever really been a good reason to do that. But it's out of just to try to make sure that Google is a good place and make sure that our access was in a good place. I worked with a Moesha who I mentioned earlier, who's our newest ARC's just core team member now, who worked at Google to set up a task force that puts the latest version of our excess into Google three, which is their Monov repository and runs it against all their Bellard target. So thousands and thousands of bill targets. Tons of apps using our just in every way you can imagine to see what breaks. And they report to us and then let us know it breaks and we work with them to resolve those issues. Well, before you would ever see a published release on NPR. So that's going to do a lot to make sure that new, especially patch releases have no breaking changes in them. The other thing that's going on is cheese. I don't know, understand why this is. Sorry. So the thing about this is these two gigglers are helping us with these efforts. And I really want to thank them, Christine and Michael James. I don't know if they're watching, but they have worked tirelessly to help us updates Google three through this. It's a major release that we're doing right now from six to seven. So there are some breaking changes. So they've been working to update through those breaking changes and working with us on what what we need to change on our end and what they might need to change on their end in order to get those things out and make sure that this release is good. So another thing is we're on the latest version of typescript now, so three. Eight. And that means we can use the latest features in typescript. And we've made a lot of typing changes, particularly things to generics that will help you out. So you get better type inference in our students. So, for example, an argument insurance. Now, what I what I mean by this is basically everywhere we can where you are passing in a rest of arguments. We do our best to try to figure out what those arguments are. What say. There's a whole bunch of different observables or something like that. And return and observable that matches all those types. So before we might have had an upper bound limit of like eight or nine values. And then after that, we couldn't type anymore. Now we have to go up to any number of values and TypeScript will figure it out. So one example of this would be the simplest one, which is if you haven't more than nine different types or nine values passed, it would freak out that you get a build time error in typescript and it would say, hey, one of these isn't a scheduler. And that's wrong on so many levels. When we're trying to get scheduler out of. And I'll talk about that in a bit. But to be like it just sucks that this is your experience. The other thing is the desirably didn't get back would be wrong. So it actually goes to eye and doesn't even include J. So it's it's the wrong type that you get back anyway. So even if you did get past that builder with any or something like that, you still get the wrong result. In the latest version of of our excesses is much better. So you actually get back the proper type in these scenarios and you could add 20 more in there and it would still figure out what you need. So and this is true for of and merge and all sorts of other things that take these sorts of arguments. So we fixed those. We also fixed some bad types. And what I mean by bad types are types that did not reflect the runtime behavior of actual spies. So if you noticed in the chat earlier, I was I was razzing David East a little bit about his use of to promise to promise is actually one of those that had that type. So you look at this and it looks like it's OK. So you've got you've got this. Get names and it's returning and observable of arrays of strings. And when you to promise it, everything here looks like it's just fine. But what you don't notice is the type of names that's returned from that async. Wait, wait. There's actually a string or undefined. And this is this is in version seven. And this is the correct behavior. And the reason this is the correct behavior is if names happen to be empty. It never admitted a value and it just completed two promise will resolve as undefined. And it's done that since version five. It's always done that. And that's part of legacy behavior from even before version five. And this is this meant that our typing score were incorrect. So the proper typing is to always have or undefined. Now, what that means for you is if you're using this, you're gonna sometimes see this where you maybe you were expecting a particular type of night. You await it and you have this error here. It's either the solution is to either put a bang after to promise because, you know, it's going to give you a value or just type it properly in an account of the fact that it could be undefined, because this is this is correct. It's trying to help you. So there's there's also the fact that we're deprecating to promise because of this weird behavior and we have some replacements for it that are new features in version seven that I'll talk about a little bit. So union type returns are better. We started doing this during version six and actually a few of the updates broke. People in particular, I think Captain, have emerged. But we've now got this to where we've updated it throughout the library. And what this means is if you have and this particular affects, people are using NDR X where you might have. You might you might have effects that are returning different types of actions. And it freaks out trying to figure out what type of action is being returned from inside the cat map. And you get the wrong return type from from the observable. So this this this will resolve that issue. And you won't have to, like, explicitly type things anymore. It'll just infer for it properly. All right. Let's move on to what everybody likes to talk about new features like we needed more features. All right. Yes. First one is animation frames. So this was an idea that was brought up actually last year at Engy, I believe. And what this is and you saw that animation. I'll play it one more time. What this is, is it is a static method that is an observable that fires on animation frames and gives you the milliseconds elapsed since the start of the observable. So it's useful for doing animations and it's much more useful than what the contemporaries were that people did all the time. So there's many different ways to make an observable of animation frames currently in the library. This is the old and busted ways in a world of zero with an animation frames Kendler range of zero to infinity with an animation. Prints get a timer timer. Again, same thing. These are all they'll do identical stuff. But the stink about this is if someone is doing this, it's because they know something about the internal implementation of our extras and these particular functions. It's not because it's the best way to do it. So it sucks that people had to know these recipes to do it. And we've resolved that by giving you animation frames, which again, is better because it gives you the milliseconds elapsed since it started, which is much more useful than just incrementing counter. So that's that's their frame. We also have new promised conversion functions. So these these are what I was talking about with two promise before. Slides are being so. You. So. We've got last value from this replaces two promised. All right, so last value from. What this does is it does exactly what to promise should have done and that it just waits to the last value or waits to throw the promise of complete and then resolves with the blast value. But if the promise completes without giving you a value, say, for example, you give it an empty promise, it actually will reject with an empty area that you can test for later on and say, hey, was was this was this empty like. And not just not just unobservable. That could have emitted undefined. Right. So you a promise that returned undefined or something like that. So you can actually this is much, much better behavior and then defaulted to something. So this is more of what you would expect from a promise that never get that. That never gives you a value. It's this was empty. All right. So that's much better behavior. We also created first value from. So this is the problem with two promise before, which is that people had a hard time rationalizing. Why is it the last value? Why isn't it the first value? And so on. Now it's pretty explicit. You know, when you read the code, you're awaiting the first value from this. This observable what this does, it waits for the first eye to arrive. It resolves a promise with it. And then immediately unsubscribes from that observable source, the. The other thing about this is it will also rejected an empty area. If the observable completes without without emitting a value. But just a reminder, you only want to use this when necessary. You lose cancellation when you convert to a promise. This is only for API. Is that require promises? So like legacy API as or async away, that sort of thing. Very sorry, my slides are being slow. There we go. We also added and I'm excited about this AC iterable support. So in this example, I've made this ticker with an async generator function called async ticker. And it's got this. Wait, wait in there. It's kind of funny to read. Oh, wait, wait. But wait. It's just some function that waits for a certain number of milliseconds and resolves a promise. So I've got this while. True. And basically what this is, is it is it's going to return what's called an async iterable, which when you next off of it gives you a promise to the next value, essentially to an iterator result. And now an answer. Yes, anywhere that accepted a promise or an observable before will now also accept an async iterable. So you can return it async iterable instead of catnap or to defer or something like that in what it just just just looks for that symbol, that async iterator. And you can read more about that at Mozilla, a developer network, but it provides some really interesting new possibilities. For example, I'm using defer here with an async function star. You can use a map or immerge map or something with async function star as well. And in this I'm saying, OK, well, I want to wait to load the user and then I want to start a loop that goes and does some like long pulling with a promise based API or something that goes and gets the messages for that user by user name. And when it gets it, if I have it, I want to yield those messages. And then it comes back around a loop. And then I do my processing the observable and it says, OK, well, let's do the next one. And so Defer is going to give me an observable of user messages via this long pulling that I think you can compose in interesting ways with with an async function. We chose not to add conversion the other way around into the core of the library, the functionality was written into that PR by yours truly. But we talked about it in the core team meeting and we decided that it would be best to split that off to the side for now, because there is a lot of different ways to take unobservable and convert it to an async iterator, where there's only really one valid way you should consume and async iterator as an as an observable. So we decided you can consume amazing iterators with our express, but to convert from an observable. The other direction. There's this other library, which again, is the exact code that we had in. We're going to put in our access. We've just put it in its own library called our Express or a weight. And you can see there on the side there's an example where it's doing each value from source, where that's going to do subscribe to the source. It's going to wait for a value from that source or and or as it gets values is going to buffer them up. And then it's gonna go through that for a weight. There's actually four different ways you can use it. There's each value from that gives you every single value, one at a time. There's Bufford values terms that takes the Bufford values that have arrived while you were going through that loop. And just gives you the whole buffer every single time you hit the top of that loop. Or when that when something arrives, there is latest value from which gives you the most recent value that arrive from the source. And next value from which we'll wait for the next flight to arrive from the source where it goes back. So these are all really interesting features. The other thing that you might want to check out if you're interested in executables, is I. J. S. So this is also developed by members of the Arctic ice core team. So Matt Osaki in particular, and Paul Taylor, I've been working really hard and I expressed this is basically ARC's J. S, but for executables, it's got different use cases. It's particularly useful, I think, for node, but it's pull based instead of push based. So go check that out. Sorry though. This is one thing about async iterable is is async await the promises returned by them zones can't patch it. So it will cause problems in zone. I'm sure there's probably workarounds for this that I'm just not aware of. But that's, that's something to be aware of is if you try to use these things natively, you could have problems with gess. All right, another new feature, reset, unsuccess, true for retrial. This seems minor, but it's the thing where if you have a source and it errors and you have like a retry, count three, what happens is it retried once it retried again, and then maybe it starts being successful again for a while. But then when it airs again in version six, it would only have one retrial left. It wouldn't reset that counter. So we added a feature. It's actually a non breaking change, but we added a feature called Reset Unsuccess that you can configure. And basically what that just says is if you do get one successful message through, then reset the counter back to three. So it's useful for some folks. Another new feature, but they're not really new features are just renamed Concat with merge with zip with with with with with. So basically what this is, is we took all of our legacy operators like race zip combined. This merging cat that we're operators that had the same name as some of their creation methods and we rename them to be tampered with in the end. And that kind of is more uniform with the rest of the operators in a library. We were going to remove them. But what we discovered, especially through working with Google, that there were still a lot of people using these in particular like cats. So these are just renames. And we are going to remove the deprecated ones and the next version. So deprecation, we have a lot of deprecation, this version. But we didn't remove hardly anything. So you shouldn't see any broken, broken code because of missing stuff. Don't selectors that they've been deprecated since 5.5. We still have them in there. Don't use them. But but they're still in there. We haven't removed them in this version. Scheduled arguments are deprecated. So, like, if you're passing schedulers to of a range or some of these other things, we want you to stop doing that. Some of the things that require schedulers like things that actually require a timing like timer or interval, that they'll probably stay there. But these are not as much. What we want you to do is use the new scheduled API, which is which was actually introduced last year and observe on which has been around for a while. So this is a better way to do that. And this is just to move forward so we can try to like pull some of the scheduling logic out of operators that really don't need it. And a lot of cases. Deprecated subscription signatures. Now, this is something where. This is going to be jarring for some folks, but we've got good reasons. During this, we're trying to we're trying to narrow down the different ways you can call, subscribe and tap, but mostly subscribe. Slow, slow. All right. So here's what's OK or we're not deprecating. So basically subscribe with one argument. If you want to think about it that way, you can do it. You can either call subscribe with a function or you call subscribe with an observer or a partial observer. The other ways will not break. You want to call it with three functions right now. It's not broken. Just deprecated. But the reason for this is, is it becomes very clear to say, oh, I want to subscribe to this and I only care about errors. You're gonna be forced to have an object in there that says error and has a function after it. Right. So, you know, which is an area which is next. The deprecated version would be like this. And you've got some you've got subscribed with multiple functions pass to it. The reason that we wanted to deprecate this is one, it's a bad developer experience. This is an experience where people have to go in. They literally have to count to figure out, am I in the next function? Am I in the error function or am I in the complete function? So it can be like no no function or no function or something like that. And it's it's just not a really good experience for folks. So it's much, much better to have an object in there where you have to name what those things are. Little more verbose maybe, but it's a better developer experience. And the other thing is internal to the library. Right now, we have this logic to reconcile. Did you pass a function or or an object or did you pass more than one function? Or are there three arguments and so on? Every time you subscribe to an observable, we have to do this reconciliation to see what you've subscribed with. So this will help us in version eight, remove all of that logic. And we can just say, did you give us a function or did you give us an object? And we know what to do with it. And it makes the library smaller and more efficient. Again, tap is the same thing. Basically subscribe and it's an operator, right? So the same thing. You want to try to provide one argument to it the other. So the other things are still there. They still work. They're just deprecated. And again, here's what it looks like, deprecated. We want to reduce the schedule of footprints in this this upcoming release, and we are. We already have. So right now, if you are. If you're if you're just using share replay, for example, that's all you use. You're going to end up including about four Quaye worth of code. That is all scheduler code that you're probably not even using at all. And it's just because replay subject is used inside of Scherrer replay and replay subject was using scheduler to get a timestamp, and that's it. Wasn't using the scheduling part of it at all. And there's several ways this could end up happening to you and you can end up bloating your app by. It didn't even mean to. So things like interval time or audit time, these other things like overtime. We want to move to where these things are, not things that are adding extra code to you unless you actually explicitly want to use scheduler. So we're going to keep moving that direction over the course of version seven non breaking ways and then eventually try to phase out passing schedules to some of these where we can for Virgine eight. One of the ways we did that is with time stamp providers. That's new in version seven. It's just an interface and it's an interface that has a now method on it that returns. No. And the reason that's interesting is we were able to default replay subjects. Third argument. So instead of defaulting it like async scheduler or whatever it was defaulted to before. Now it's defaulted to it's actually defaulted to the date object. So data objects native. We don't the ship that you could also use in this case, you can use the performance object, which has a now method on it. The returns. No, if you wanted some really, really precise caching in your replay, this subject. I don't know why you do this, but I would love to see the amazing rationale behind this anyway. But you could do that or you could pass any object just as a now method to to replace a subject and other things like time, the time interval operator. So. All right, now I want to talk about seven don't want to be on. So I just talked about all the implications and things that are going to change over time. The minor versions of seven are we may release some some small new features or there's some things that we're eyeing, but they'll be kind of off to the side of the main bulk of what you use in our express. The biggest thing we want to do is in each version we want to release. Yes. Let Transformation's or other other code transformations that help automate updating your app to not use all of the deprecated API. So really, what we want to do is make sure that every single new major version of seven that comes out. It's a it's not a breaking change because it's not a major version. So I'm sorry, a minor version as every new minor version that comes out version seven. It's not a breaking change because we're working with Google to ensure that. And these are minor improvements and we're providing new Slint rules to help you not write bad stuff. And we're actually helping you transform your code automatically away from deprecated API so that when we get to version eight, you're not jarred with this. Oh my God. Here's some huge amount of work I have to do to try to update all of my code. So version eight, the actress here is maybe it'll end up being version nine. You don't know like there something could happen where we need to introduce a breaking change to accommodate browser things or runtime things or whatever. Not likely, but it's possible. So this is finally going to be work. So this is something that I have been working on. And like, chomping at the bit to do for two years. But to be responsible, I can't just jump to a leaner, smaller version of ARC's. Yes. Without slowly migrating folks there. We have some experiments already that were done. The experimental branch is still existing. Go check them out. But like the version we settled on tends to be about 40 percent smaller and like angular sizes as far as the footprint of our express. So this is this is where we're going to finally remove everything that we can that's been deprecated as long as we were able to make Code Transformation's for it during the course of those seven. And of course, we're always going to try to keep up with the latest advancements in JavaScript and TypeScript. So there's a big things. But again, we can't even do this until we get done with all of the code transformation, migration tool type stuff. Things stuck again. All right. Yes. All right. So that one of the questions I get from a lot of folks is how can you help us? There's people that want to help the project. One area we're going to need a lot of help is if you have any expertise in doing co transformation. This is going to be a huge, important part of our project coming up. All of this is volunteer work. Nobody is being paid by a company to do massive amounts of work against the the main repository. We get some contributions every now and then from companies from Google or whatever. But Wednesday, the most of this work is done totally by volunteers and the bulk of the library work is mostly taken care of or will be taken care of by core team members. But like areas where we need help are going to be with. Yes. Code transformation's documentation needs a lot of updates because we're going to be making changes in some of the deprecated API is are still documented. We might want to remove those or change some of the wording around them or like the subscriptions, how we want people to subscribe. A lot of the subscriptions might be done and deprecated ways and some of the documentation you can help our community. This is even bigger than the first two honestly articles and how TOS videos mentoring your friends that if you're really good at our extraverts and you want to help other people or mentoring people that you don't even know online, like, please do. Some of the best experiences in my life have been from helping in some of the best benefits to my career. And then from helping people that I don't know on the Internet. So I highly recommend doing that. Doing some research on our access or developer tools, like if you want to do research like who was using what operators or whatever, like that, just useful dots. And we're happy to work with you on all of that stuff. If you're if you're doing something compelling, we'd love to help you out. We'd love to interact with you on these things. And, of course, making libraries. So if you're building a library with our express or that's built around a reactivity in our chest, please reach out to us and let us know about it and ask us how we can help you. And then, you know, do what you can do. Well, we'll do it. We can do it to get it out there, because these libraries give people more exposure. Access, which helps build the knowledge base, which helps makes everyone experience everyone's experience working with it that much better. So thank you. That's all I have. Please stay safe this year. These are extraordinary times. I hope you have a fantastic weekend and.