Exploring the Patterns in the Operators

John Lindquist
InstructorJohn Lindquist
Share this video with your friends

Social Share Links

Send Tweet
Published 4 years ago
Updated 4 years ago

Instructor: [0:00] I hope this course has been able to show you that closures, callbacks, and composition can handle pretty much any scenario. I'd like to take a second to look through operators and just call out where the closures are, where the callbacks are, and wrap this up.

[0:13] Because you see values here which are captured inside of this function, this function is the closure around these, and the closure manages when something's ready, a shared value, and keeping a list of future listeners, which are passed in.

[0:30] The callbacks are these functions, because they are functions that are invoked inside of another function. That broadcaster's invoked there, this listener's invoked there, and that would share first.

[0:41] In our map broadcaster cache, you can see these values, which are wrapped in this closure. They're allowing us to cache values. If this were to live inside of this function in here somewhere, then that cache would be cleared every single time, but because it's extracted out of it, this closure can now have cached values.

[0:59] Cancel is the most common example we've used, where we're capturing another function and tracking it to make sure we're cancelling the right thing. Then the callbacks, or again, the broadcaster, and the listener, which are functions passed in to be invoked by other functions.

[1:13] Ignore error does not have any closures. It's just the callbacks for listener and for broadcaster. Map error being the same. Again, the pattern that's established is that because we're passing in broadcasters and listeners last, each time, you can see I highlighted that and all of those are highlighted, because it's the exact same text.

[1:36] That means that these functions are able to work together in a way that allows us to compose them and use them together. Wait for, captures the cancel timeout. This would be the closure here. Filter by key was just configuring and operator we created above. Allow when, also has a closure to capture the current.

[1:54] Again, as always, that same pattern of broadcaster and listener. Map sequence allows us to create that buffer and track an inner broadcaster so that those aren't lost every time this function is called. You can see these values are captured by this closure, which allows us to call broadcasters in order. On and on and on, it follows that same pattern.

[2:14] I would say the most important part of the pattern is that listener is last, and when different functions share the same last argument, it means they can be composed together. The fact the broadcaster is next to last, allows us to use all of these operators together.

[2:28] The fact that this argument comes first, it means we can use these other functions in the same context of these closures, where when we redefine the new listener we have access to these values. I'm not saying that all this code is perfect or bug-free. There's an infinite amount of asynchronous scenarios. I was trying to keep the examples short but still complex enough to highlight these patterns.

[2:50] The most important and biggest takeaway of all is that these functions allow us to capture this logic in a reusable way in a way that works cleanly with the other parts of our app.

[3:00] Whether it's a pattern similar to this one where you're doing these operators, lots of closures to capture values and callbacks that you hook together, or you use a popular library that uses the same concepts, but uses a completely different pattern.

[3:16] I hope that exploring the inner workings of these things helped you to understand the ideas behind capturing logic inside of functions and then extracting those functions into a library.