This repository is a workshop to explain the main concepts of RxJS starting from the implementation.
The main idea is to implement the key features to gain a deep understanding of the architecture and model proposed by reactive programming, as well as to explore functional concepts that are very useful for simplifying reasoning about the implemented types.
From the perspective of a type, what interests us is knowing how it is created, how it is combined, how it is transformed, and how it is destroyed. Therefore, this workshop will have unit tests to verify each aspect. Participants will have to implement creation operators, combination operators and transformation operators.
By default, the tests come with the ".skip" modifier. The idea is to gradually remove them until we have a fully functional library.
Once the operator is implemented (in teams), a Pull Request (PR) will be created and merged with the main branch, while ensuring that it passes the tests successfully.
It is very important that the added commits follow the Conventional Commits convention to ensure smooth integration in the CI (Continuous Integration) pipeline. The prefixes to be used are:
feat: for new features fix: for bug fixes docs: for documentation updates style: for code style changes (e.g., formatting) refactor: for code refactoring without adding new features or fixing bugs test: for adding or modifying tests chore: for other changes that do not affect the code (e.g., build configuration, dependencies) Following this convention helps in maintaining a clean commit history and facilitates automated processes in the CI pipeline.
A sandbox.js file is also provided for live code testing. You can execute this file by using the command "yarn sandbox".
Clone workshop:
git clone https://github.com/qustodio/workshop-rx-from-inside.git
Install dependencies:
yarn install
All test:
yarn test --watch
Single test:
yarn test path/to/test.spec.js --watch
yarn sandbox
- Observable as value producer
- Observer as a distributor of values, error signal, and completion.
- Subscription as cancellation of value production.
- Defining rules for error, cancellation and completion.
Goals:
At this stage, you should be familiar with the concepts of hot observables and cold observables. Additionally, you should be able to propose alternatives for combining these behaviors (multicast).
Exercises: Creation helpers
- Implement from (iterators, strings and promises)
- Implement of (for any value)
- Implement interval (without completion)
- empty (observable without values)
- What is an operator?
- Improving syntax for composing operators (pipe)
- IMPORTANT: Endomorphisms and monoids (functional tool).
- Extending the architecture: Subject and Replay Subject
- Implement share and shareReplay operators
Goals:
At this point, you should be able to create your own operators and utilize endomorphisms and monoids in other aspects to compose infinitely.
Exercises: Creation helpers
- Implements map
- Implements filter
- Implements take
- Implements scan
- Implement first (from take)
- Handling errors with streams, using the tryCatch operator.
Goals:
At this stage, you will be able to compose error-handling reactive streams. Remember that when capturing a stream, we should always return an observable.
Exercises: Error handling helpers
- Implements tryCatchOperator
- The importance of completing streams
- Different ways of combining, merging, and concatenating.
- IMPORTANT: foldables and monoids to simplify reasoning (functional tool).
Goals:
At this point, you should feel comfortable using monoids and foldables to simplify reasoning. You should also be able to create your own combination operators.
Exercises: combining observables
- Implement merge (variadic version)
- Implement concat (variadic version)
- How to reduce nesting complexity?
- What is a monad?
Goals:
At this stage, you should understand what a monad is and how it helps us reason in a flat manner, avoiding the additional complexity that nesting introduces.
Exercises: The problem of nesting
- Implement switchMap
- Implement mergeMap
- Observable as a first-class object
Goals:
Exercises: Operators that take other observables
- Implement takeUntil
- Implement takeWhile
- Why do observables compose so well?
- What are the components of this architecture?
- What algebraic data types have you used?
- How do algebraic data types facilitate reasoning?
- Can you describe how redux-observable operates, perhaps provide an implementation?
- The solutions can be found in the "feature/solutions" branch.