Retrieving an Observable within an Observable is a feature found in Angular 9

Seeking a solution to return an Observable nested within another Observable. Although I've tried using the pipe and map operators, it doesn't appear to be functioning correctly for me. What could be causing the issue?

My development environment includes Angular 9.1.12 and rxjs ~6.5.4.

For instance:

Service1
import { Observable, of } from 'rxjs';

export class Service1 {

  test(): Observable<string> {
      console.log(1);
      return of('hey');
  }
}

Service2

import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

export class Service2 {

  constructor(private service1: Service1) {}

  test(): Observable<string> {
    return this.service1.test().pipe(
      map((value: string) => {
        console.log(2);
        return value;
      })
    );
  }
}

Component

import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

export class Component implements OnInit {

  constructor(private service2: Service2) {}

  test(): Observable<void> {
    return this.service2.test().pipe(
      map((value: string) => {
        console.log(3);
      }));
    }
  }
}

Only "1" is displayed in the console.

Answer №1

It makes sense because you didn't subscribe to the observables, so they were never actually emitted or executed.

You need to subscribe in the component like this.

this.test().subscribe();

I have put together a stackblitz for you to experiment with.

PS: Remember to also unsubscribe when necessary. If these concepts are new to you, I recommend reading this article.

Answer №2

Similar to how functions only execute the code inside them when called upon, Observables run their code only when you subscribe.

When you call this.service1.test(), you will see an output of 1.

However, outputs 2 and 3 are not visible because you do not subscribe to those specific Observables.

export class Component implements OnInit {

  constructor(private service2: Service2) {}

  test(): void {
    this.service2.test().pipe(
      map(_ => console.log(3))
    ).subscribe();
  }
  
}

Answer №3

In the world of observables, there are two main categories: hot and cold. For the purpose of this discussion, we will focus on cold observables. Hot observables can be explored further here.

Cold observables, true to their name, wait to execute their internal logic until they have been subscribed to. This means that when you subscribe within a component, it triggers all the observables up to the innermost of('hey').

export class Component implements OnInit {
  constructor(private service2: Service2) {}

  ngOnInit() {
    this.test().subscribe();
  }

  test(): Observable<void> {
    return this.service2.test().pipe(
      tap((value: string) => console.log(value))
    );
  }
}

It's important to note that using the map operator in a component without a return statement will result in returning undefined. The map operator is typically used for transforming incoming values, while the tap operator is more suitable for side-effects like logging.

Unsubscribe

Additionally, subscriptions remain open unless an error occurs or they are explicitly completed. It's advisable to close these subscriptions once they are no longer needed.

For instance, in Angular, it's common practice to handle subscription closure in the ngOnDestroy hook to ensure they are closed when the component is destroyed.

export class Component implements OnInit, OnDestroy {
  sub: Subscription;

  constructor(private service2: Service2) {}

  ngOnInit() {
    this.sub = this.test().subscribe();
  }

  test(): Observable<void> {
    return this.service2.test().pipe(
      tap((value: string) => console.log(value))
    );
  }

  ngOnDestroy() {
    if (!!this.sub)
      this.sub.unsubscribe();
  }
}

There are various ways to gracefully handle closing open subscriptions. More details can be found here:

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Discovering all images in Angular

I have a function that stores image data, including the name. Using *ngFor, I am able to fetch this data from the database and display it in boxes. HTML <div class="row tab-pane Galeria"> <div *ngFor="let product of products" (click)="Im ...

Having trouble installing dependencies in a React project with TypeScript due to conflicts

I encountered a TypeScript conflict issue whenever I tried to install any dependency in my project. Despite attempting various solutions such as updating dependencies, downgrading them, and re-installing by removing node_modules and package-lock.json, the ...

What could be causing issues with my unit tests in relation to Angular Material tooltips?

I have a unique and specific issue with the following unit test code. It is very similar to another working file, but I am encountering an error related to mdTooltip from the Angular Material library. Here's the problematic portion of the code: Phant ...

Accessing URLs directly with the Angular 2 Router

I currently have a file named main.component.ts with the following code: It can be found in: root/ import {Component, OnInit, OnChanges, IterableDiffers} from 'angular2/core'; import {TypeService} from './type/type.service'; import { ...

Angular navigation system featuring hierarchical categories

My goal is to organize categories in a nest structure, but without setting a predetermined limit on the number of levels. Depending on various factors, there could be anywhere from 3 to 5 levels. For example, level 1 could be "categoryX/1", level 2 "categ ...

A Guide to Filtering MongoDB Data Using Array Values

I am trying to extract specific data from a document in my collection that contains values stored in an array. { "name": "ABC", "details": [ {"color": "red", "price": 20000}, {" ...

Error in Typescript: The property 'a' is not defined in the type 'A'

Here is an example of the different types I am working with: type Place = { address: string } type Location = { latLng: string } type User = { name: string } & (Place | Location) When attempting to parse the data using this structure, I enco ...

What is the best way to click on a particular button without activating every button on the page?

Struggling to create buttons labeled Add and Remove, as all the other buttons get triggered when I click on one. Here's the code snippet in question: function MyFruits() { const fruitsArray = [ 'banana', 'banana', & ...

What exactly does the question mark represent in the code structure as indicated in VSCode?

When looking at the image, you can see that in the description of done(), VSCode indicates the type of parameters using a colon error: any or sometimes with a question mark and colon user?: any. So, what exactly is the distinction between these two ways o ...

Is the select all checkbox causing disabled checkboxes to be selected in an Angular environment?

<div *ngIf="showLog"> <!-- <p *ngIf="metricExecutionList Blockquote ===null">No Records Found</p> --> <div> <p-table #dt [value]="metricExecutionList" [l ...

When attempting to run npm install for @types/jquery, an error is returned stating "Invalid name: @types/jquery"

npm install @types/jquery npm ERR! Windows_NT 10.0.10586 npm ERR! argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-c ...

Here is a unique version: "Dealing with Node.js ES6 (ESM) Modules in TypeScript can be tricky, especially when the TypeScript Compiler (TSC) fails to emit the

I am facing an issue while transpiling my TypeScript project to JavaScript. I have set the project to resolve as an ES6 Module (ESM) by using the "module":"ES6" configuration, but the problem persists. This is the current setup in my ...

Issue with accessing data in React Admin Show Page using useRecordContext() function leads to undefined return

Within a basic RA application, I am attempting to showcase an item known as a "card" utilizing a Show Page. The fields—specifically id and title—are being presented correctly. Nevertheless, the useRecordContext() hook is consistently returning undefin ...

The placeholder string is being accepted as the input value for the number

My issue is with a form input of type number. When the form is submitted without entering any number, it treats the placeholder text "rating" as the value. How can I stop this from happening? I need to make sure that the input number field is marked as in ...

Issues arise with Typescript Intellisense in Visual Studio Code causing it to stop functioning

I'm currently exploring the world of building desktop applications using Electron and Typescript. After selecting Visual Studio Code as my IDE, everything was going smoothly and I managed to successfully load a sample HTML file into Electron. However ...

Tips for crafting a test scenario for input alterations within Angular

Hello there, currently I am working on an application using Angular and TypeScript. Here is a snippet of my template code: <input type="text" placeholder="Search Results" (input)="searchInput($event)"> And here is the TypeScript code for the searc ...

What causes the variation in Http Post Response between the Console and Network response tab?

Currently, I am tackling an issue in angular2 related to HTTP post response. The problem arises when my endpoint is expected to return a boolean value. Interestingly, the response appears correctly in Chrome's Network response tab; however, upon loggi ...

Can someone point me in the direction of the AND and BUT keywords within the cucumber library

After adding the following libraries to my Angular project: "@cucumber/cucumber": "^7.2.1", "@types/chai": "^4.2.16", "protractor-cucumber-framework": "^8.0.2", I noticed that when I open the cuc ...

Having trouble implementing catchError in a unit test for an HttpInterceptor in Angular 11

I am facing challenges in completing a unit test for my HttpInterceptor. The interceptor serves as a global error handler and is set to trigger on catchError(httpResponseError). While the interceptor functions perfectly fine on my website, I am struggling ...

Roll out a custom-built server for an Angular 7, MongoDB, Express, and Node application

I am seeking to host my Angular application with Node.js, MongoDB, and Express.js on a server of my own. My current deployment method involves: -> ng build --prod (generates output in the dist folder) -> ng serve from the dist directory To start the back ...