<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rebekah van Wyk</title>
    <description>The latest articles on DEV Community by Rebekah van Wyk (@rebekahvanwyk).</description>
    <link>https://dev.to/rebekahvanwyk</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2727811%2Fd860e7e3-b1c2-4ed7-9a06-500be2a7ddc2.png</url>
      <title>DEV Community: Rebekah van Wyk</title>
      <link>https://dev.to/rebekahvanwyk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rebekahvanwyk"/>
    <language>en</language>
    <item>
      <title>Reactive Programming and Observables with RxJS</title>
      <dc:creator>Rebekah van Wyk</dc:creator>
      <pubDate>Mon, 08 Sep 2025 22:03:03 +0000</pubDate>
      <link>https://dev.to/rebekahvanwyk/reactive-programming-and-observables-with-rxjs-3efi</link>
      <guid>https://dev.to/rebekahvanwyk/reactive-programming-and-observables-with-rxjs-3efi</guid>
      <description>&lt;p&gt;According to the &lt;a href="https://rxjs.dev/" rel="noopener noreferrer"&gt;RxJS docs&lt;/a&gt;, RxJS, or &lt;em&gt;Reactive Extensions for JavaScript&lt;/em&gt;, is a library "for &lt;strong&gt;reactive programming&lt;/strong&gt; using &lt;strong&gt;Observables&lt;/strong&gt;, to make it easier to compose &lt;strong&gt;asynchronous&lt;/strong&gt; or callback-based code”. In this article, we’ll break down the core concepts behind reactive programming and how RxJS makes it easier to work with asynchronous data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reactive Programming
&lt;/h2&gt;

&lt;p&gt;To understand what reactive programming is, we should first understand &lt;strong&gt;data streams&lt;/strong&gt;. A &lt;strong&gt;data stream&lt;/strong&gt; is a flow of potentially infinite data, where the data can arrive at various points in time. &lt;/p&gt;

&lt;p&gt;Visually, it might look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd3lqhirslhhp8kuqxg5p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd3lqhirslhhp8kuqxg5p.png" alt="Visual representation of a data stream" width="800" height="152"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;where the dotted line represents time, and our nodes A, B, and C represent data points arriving at different points in time. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reactive programming&lt;/strong&gt; is a paradigm that focuses on data streams and &lt;strong&gt;change propagation,&lt;/strong&gt; meaning that when new data arrives, any part of our system that relies on this data automatically reacts and changes accordingly.&lt;/p&gt;

&lt;p&gt;RxJS helps us to achieve this through &lt;strong&gt;Observables&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Observables?
&lt;/h2&gt;

&lt;p&gt;Put simply, Observables are data producers that represent a data stream. They emit notifications that we can consume. &lt;/p&gt;

&lt;p&gt;There are three types of notifications that can be emitted from an Observable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next&lt;/strong&gt; notifications deliver a value emitted by the Observable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error&lt;/strong&gt; notifications indicate that something has gone wrong during the Observable's execution&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complete&lt;/strong&gt; notifications indicate that the Observable has successfully finished its execution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of these notifications are useless to us, however, if we don't have the relevant Observers and Subscriptions in place to effectively consume these notifications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Observers and Subscriptions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Observers&lt;/strong&gt; define how each type of notification from an Observable is handled. &lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;subscription&lt;/strong&gt; is what actually connects an Observable to an observer. Without a subscription, the Observable would remain idle, and its logic would never run.&lt;/p&gt;

&lt;p&gt;The subscribe() method of RxJS creates a subscription, and the unsubscribe() method ends a subscription. Something to note is that once a notification of type &lt;strong&gt;error&lt;/strong&gt; or &lt;strong&gt;complete&lt;/strong&gt; is emitted from an Observable, the subscription is automatically ended, and nothing further will be emitted by the Observable.&lt;/p&gt;

&lt;p&gt;Overall, the relationship between Observables, Observers, and Subscriptions, looks something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fngvxxygrk2i1xv81yz3e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fngvxxygrk2i1xv81yz3e.png" alt="Relationship between Observables, Observers, and Subscriptions" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is it important to unsubscribe?
&lt;/h3&gt;

&lt;p&gt;In Angular, components can live for a long time. If you forget to unsubscribe from long-running streams, you risk memory leaks, performance issues, and in the worst case scenario, your app could even crash. &lt;/p&gt;

&lt;p&gt;Let's have a look at a very simple &lt;strong&gt;code example&lt;/strong&gt; of an Observable in action.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// create an Observable&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observable$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;subscriber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;subscriber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;First emission&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;subscriber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Second emission&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;subscriber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// indicates that we're done and unsubscribes&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;subscriber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Final emission&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// define an Observer&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Received: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Done&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// subscribe to start receiving values&lt;/span&gt;
  &lt;span class="c1"&gt;// pass our Observer to our subscribe function&lt;/span&gt;
  &lt;span class="nx"&gt;observable$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the Observer has indeed defined how notifications from the Observable will be handled; relevant messages will be logged to the console. We'd see the following logged to the console when this execute() method is run:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the string "Received: First emission" synchronously&lt;/li&gt;
&lt;li&gt;the string "Received: Second emission" after 2 seconds&lt;/li&gt;
&lt;li&gt;the string "Done" after 3 seconds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then, despite there being another next notification defined, we'd see nothing further in the console due to the &lt;strong&gt;complete&lt;/strong&gt; notification ending the subscription to our Observable. In a more practical example, the number or timing of emissions from our Observable may be unknown, and we'd need to unsubscribe more explicitly. You can learn more about ways to do that in Angular &lt;a href="https://dev.to/hassantayyab/unsubscribing-from-observables-in-angular-a-comprehensive-guide-jf8"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While this example is a valid way to work with Observables, in practice we tend to make use of functions in RxJS called &lt;strong&gt;operators&lt;/strong&gt; to work with Observables more cleanly and easily.&lt;/p&gt;

&lt;h2&gt;
  
  
  RxJS Operators
&lt;/h2&gt;

&lt;p&gt;As we've just mentioned, RxJS operators are simply functions defined by RxJS which make it easier to work with Observables. There are various types of operators, as listed &lt;a href="https://rxjs.dev/guide/operators#categories-of-operators" rel="noopener noreferrer"&gt;here on the RxJS docs&lt;/a&gt;. We would typically make use of these operators to do things like transform, filter, and combine streams of data easily. Let's look at two important categories of RxJS operators: creation operators and pipeable operators.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creation operators
&lt;/h3&gt;

&lt;p&gt;Creation operators create new Observables with pre-defined behaviour, or by joining other Observables. They can be called as standalone functions.&lt;/p&gt;

&lt;p&gt;Some popular creation operators are of(), combineLatest(), and merge(). We'll just have a brief look at the of() operator.&lt;/p&gt;

&lt;h4&gt;
  
  
  of()
&lt;/h4&gt;

&lt;p&gt;The of() operator returns an Observable that simply emits the provided arguments &lt;strong&gt;synchronously&lt;/strong&gt; and then completes.&lt;/p&gt;

&lt;p&gt;Code snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Logs:&lt;br&gt;
1&lt;br&gt;
2&lt;br&gt;
3&lt;/p&gt;
&lt;h3&gt;
  
  
  Pipeable operators
&lt;/h3&gt;

&lt;p&gt;Pipeable operators start with an Observable as input, transform or update the emissions of that Observable in some way, and then return the result as a new Observable. These operators are used with RxJS's &lt;strong&gt;pipe()&lt;/strong&gt; method.&lt;/p&gt;

&lt;p&gt;Let's have a look at a couple of the most commonly used pipeable operators, namely map() and filter().&lt;/p&gt;
&lt;h4&gt;
  
  
  map()
&lt;/h4&gt;

&lt;p&gt;The map() operator applies a function to each value emitted from the Observable. &lt;/p&gt;

&lt;p&gt;Code snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Logs:&lt;br&gt;
10&lt;br&gt;
20&lt;br&gt;
30&lt;/p&gt;
&lt;h4&gt;
  
  
  filter()
&lt;/h4&gt;

&lt;p&gt;The filter() operator only passes values that match a specified predicate.&lt;/p&gt;

&lt;p&gt;Code snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Logs:&lt;br&gt;
2&lt;br&gt;
4&lt;/p&gt;

&lt;p&gt;The beauty of the pipe() function is that it allows us to chain operators together to perform powerful operations. For example, we could combine the &lt;strong&gt;map&lt;/strong&gt; and &lt;strong&gt;filter&lt;/strong&gt; operators in the following way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;     
  &lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Logs: &lt;br&gt;
30&lt;br&gt;
40 &lt;br&gt;
50&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;a href="https://rxjs.dev/guide/operators#marble-diagrams" rel="noopener noreferrer"&gt;Marble diagrams&lt;/a&gt; are a great visual tool to help us understand how each RxJS operator works. &lt;a href="https://rxmarbles.com/" rel="noopener noreferrer"&gt;RxMarbles&lt;/a&gt; is a website with very useful interactive marble diagrams that can be used to help deepen your understanding of various RxJS Operators. I suggest having a look to further your understanding of the above examples.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Real-world applications of Observables
&lt;/h2&gt;

&lt;p&gt;Observables are most valuable in cases where code is asynchronous or event-driven in nature. Examples of such scenarios include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handling HTTP requests &lt;/li&gt;
&lt;li&gt;Managing UI events such as clicks, scrolls, and key presses&lt;/li&gt;
&lt;li&gt;Working with State Management libraries such as NgRx&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Observables provide a clean way to handle data as it arrives, making it much easier to manage these kinds of scenarios.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This introduction to RxJS Observables highlighted how they provide a powerful way to handle asynchronous and event-driven data. We discussed how combining Observables with operators enables you to transform, filter, and combine data streams with ease, making reactive programming more intuitive and achievable. I hope this post provided some clarity around what Observables are, how they work, and why they are useful to us. Thanks for reading!&lt;/p&gt;

</description>
      <category>angular</category>
      <category>rxjs</category>
    </item>
    <item>
      <title>The basic components of a unit test in Angular</title>
      <dc:creator>Rebekah van Wyk</dc:creator>
      <pubDate>Fri, 17 Jan 2025 11:49:48 +0000</pubDate>
      <link>https://dev.to/rebekahvanwyk/the-basic-components-of-a-unit-test-in-angular-1103</link>
      <guid>https://dev.to/rebekahvanwyk/the-basic-components-of-a-unit-test-in-angular-1103</guid>
      <description>&lt;p&gt;When I hear the phrase “unit test”, my thoughts typically gravitate toward backend systems. Unit testing is common and expected in backend systems but seems to be overlooked when discussing frontend development. However, frontend unit testing is not only beneficial for many reasons, but it’s also simpler than it might at first appear. In this introduction to unit testing in Angular, we’ll discuss why unit testing is worth it and then walk through the common components typically found in an Angular test file.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a unit test?
&lt;/h2&gt;

&lt;p&gt;Unit tests aim to test small components of an application in isolation and typically compare actual behaviour with expected behaviour in order to verify that code works correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of unit testing in Angular
&lt;/h2&gt;

&lt;p&gt;Unit testing can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Aid in identifying bugs during development rather than in production&lt;/li&gt;
&lt;li&gt;Save time and money through the aforementioned early bug detection&lt;/li&gt;
&lt;li&gt;Help to maintain or improve code quality by encouraging developers to write more readable, maintainable, and reusable code&lt;/li&gt;
&lt;li&gt;Give developers confidence that new code additions are not breaking existing code &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Overall, unit testing is beneficial for any application. So, what does unit testing look like in Angular? Let's discuss that, starting with the files where the magic happens: spec files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Specification (spec) files
&lt;/h2&gt;

&lt;p&gt;If you use the Angular CLI to generate a new component, you will notice that four files are automatically generated: an html file, a css file, a typescript file, and lastly, a spec file. The spec file is where you’ll write the unit tests for the associated component. These tests are run using &lt;strong&gt;Jasmine&lt;/strong&gt;, a JavaScript testing framework.&lt;/p&gt;

&lt;p&gt;As I mentioned before, unit testing for frontend is often overlooked. Applications don’t need the spec file to function, and so spec files are often deleted to avoid clutter. Let’s understand the contents of these files so that we can use them to improve our applications instead!&lt;/p&gt;

&lt;p&gt;The spec file generated alongside each Angular component looks something like this at first (borrowed from this website: &lt;a href="https://esketchers.com/angular-unit-testing-using-jasmine-and-karma/#:%7E:text=What%20is%20Karma%3F,devices%20like%20phones%2C%20and%20tablets" rel="noopener noreferrer"&gt;https://esketchers.com/angular-unit-testing-using-jasmine-and-karma/#:~:text=What%20is%20Karma%3F,devices%20like%20phones%2C%20and%20tablets&lt;/a&gt; ) :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';

describe('AppComponent', () =&amp;gt; {
 beforeEach(async () =&amp;gt; {
   await TestBed.configureTestingModule({
     imports: [
       RouterTestingModule
     ],
     declarations: [
       AppComponent
     ],
   }).compileComponents();
 });

 it('should create the app', () =&amp;gt; {
   const fixture = TestBed.createComponent(AppComponent);
   const app = fixture.componentInstance;
   expect(app).toBeTruthy();
 });

 it(`should have as title 'AngularUnitTesting'`, () =&amp;gt; {
   const fixture = TestBed.createComponent(AppComponent);
   const app = fixture.componentInstance;
   expect(app.title).toEqual('AngularUnitTesting');
 });

});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When I first saw one of these files, I was quickly intimidated by the various blocks using keywords and function names I’d never seen before, such as ‘describe’, and ‘it’ - but things make a lot of sense when we break them down!&lt;/p&gt;

&lt;h2&gt;
  
  
  But first, a bit more about the Jasmine framework
&lt;/h2&gt;

&lt;p&gt;If you’re looking into unit testing, there’s a good chance you’ve come across the term Test-Driven Development, or TDD. TDD involves writing tests for expected software functionality before developing said functionality and then making sure that when the functionality is implemented, the written tests (which should have been failing when first written) now pass. &lt;/p&gt;

&lt;p&gt;Jasmine is described as a &lt;strong&gt;Behaviour-Driven Development (BDD)&lt;/strong&gt; framework. BDD is an extension of TDD, so, as with TDD, when following BDD methodology tests are often written before the functionality they’re intended to test. However, BDD differs from TDD in that BDD focuses on the behaviour of the application that the user expects.&lt;/p&gt;

&lt;p&gt;For example, say we have a method called add which adds two numbers together. A TDD-style test might ask, does add(2, 3) return 5? Whereas a BDD-style test would focus on the fact that when two numbers are added, the user should see their sum displayed. So, when writing Angular unit tests with Jasmine, we can expect to see some BDD-style traits.&lt;/p&gt;

&lt;p&gt;Now, onto that spec file breakdown!&lt;/p&gt;

&lt;h2&gt;
  
  
  The basic functions and tools found in a spec file
&lt;/h2&gt;

&lt;p&gt;Have a look at this code snippet from the Jasmine documentation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;describe("A suite is just a function", function() {
    let a;

    it("and so is a spec", function() {
        a = true;

        expect(a).toBe(true);
    });
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's walk through what we can see.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;it&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;it&lt;/strong&gt; is a global Jasmine function. It is used to define what are called &lt;strong&gt;specs&lt;/strong&gt; (our tests). This function takes in a string and a function, where the string names the spec and the function is the spec itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;describe&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;describe&lt;/strong&gt; is used to group related specs. This group of related specs is referred to as a &lt;em&gt;&lt;strong&gt;suite&lt;/strong&gt;&lt;/em&gt;. Like the &lt;strong&gt;it&lt;/strong&gt; function, &lt;strong&gt;describe&lt;/strong&gt; is a function that takes in a string: here this string names the collection of specs. &lt;/p&gt;

&lt;p&gt;When the string from the &lt;strong&gt;it&lt;/strong&gt; function parameters is concatenated onto the end of the string from the &lt;strong&gt;describe&lt;/strong&gt; parameters, you should be able to read it as you would an ordinary sentence. In this case, we’d read “A suite is just a function and so is a spec”. This sort of natural language definition of a test aligns with the principles of BDD, emphasizing clarity and readability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;Expectations and Matchers&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As we mentioned earlier in this post, a unit test typically compares actual and expected values. In a Jasmine unit test, this comparison is achieved with the use of the &lt;strong&gt;expect&lt;/strong&gt; function and what are called &lt;strong&gt;matcher&lt;/strong&gt; functions. &lt;/p&gt;

&lt;p&gt;The expect function takes in the “actual” value, and the matcher will take in the “expected” value. The matcher will use the actual and expected values to assert either true or false, and Jasmine will use this information to determine whether the spec should pass or fail.&lt;/p&gt;

&lt;p&gt;A wide range of matchers exist to verify different things. For example, in the snippet above, the matcher “toBe” simply expects the actual value to be equal to the expected value. But say we want to compare numerical values with some leeway; we could use the "toBeCloseTo" matcher, which expects the actual value to be within a parameter-defined precision range of the expected value. Jasmine also caters for cases when a developer might like to write custom matchers for their own unique purposes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup and Teardown
&lt;/h2&gt;

&lt;p&gt;The last aspect of an Angular unit test that we'll be discussing are the functions made available for setup and teardown. The purpose of these functions is to prepare and clean up the environment for test execution. They help to ensure that specs are isolated, reproducible, and free from interference caused by the state left over from other specs. Jasmine provides a few functions to help developers with setup and teardown, namely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;u&gt;beforeEach&lt;/u&gt;: called before every spec in the describe block in which it is used&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;afterEach&lt;/u&gt;: called after every spec in the describe block in which it is used&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;beforeAll&lt;/u&gt;: called once before any of the specs in the describe block are run&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;afterAll&lt;/u&gt;: called once after all of the specs in the describe block have run&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's a code snippet to demonstrate some of beforeEach and afterEach in action (courtesy of the Jasmine documentation found at &lt;a href="https://jasmine.github.io/archives/2.4/introduction" rel="noopener noreferrer"&gt;https://jasmine.github.io/archives/2.4/introduction&lt;/a&gt; )&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;describe("A spec using beforeEach and afterEach", function() {
var foo = 0;

beforeEach(function() {
  foo += 1;
});

afterEach(function() {
  foo = 0;
});

it("is just a function, so it can contain any code", function() {
  expect(foo).toEqual(1);
});

it("can have more than one expectation", function() {
  expect(foo).toEqual(1);
  expect(true).toEqual(true);
});
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, from the same source, beforeAll and afterAll in action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;describe("A spec using beforeAll and afterAll", function() {
var foo;

beforeAll(function() {
  foo = 1;
});

afterAll(function() {
  foo = 0;
});

it("sets the initial value of foo before specs run", function() {
  expect(foo).toEqual(1);
  foo += 1;
});

it("does not reset foo between specs", function() {
  expect(foo).toEqual(2);
});
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Something important to note about beforeAll and afterAll is that although they may be useful to reduce the cost of setup and teardown, since they are only called once and are not reset between specs, using these functions can easily cause false positives and negatives in your specs due to state leakage from other specs. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This beginner's guide provided an explanation of what unit testing is and why it's just as important in frontend development as it is in backend development. We then walked through what a unit test looks like in Angular and discussed some of the common functions provided by the Jasmine framework. I hope this post has cleared up some of the confusion you might feel when encountering a spec file for the first time and inspired you to embrace thorough testing in your application!&lt;/p&gt;

</description>
      <category>angular</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
