Learning how to merge two observable streams in Angular2 by utilizing RxJS and the powerful .flatMap method

Within my Angular2 app, I have created an Observable in a Service called ContentService. Here is a simplified version of the code:

@Injectable()
export class ContentService {

    constructor(private http:Http, private apiService:ApiService) {

        this.content = this.http.get('src/i18n/en.json')
            .map((res:Response) => {
                let json: {} = res.json();
                return mapData(json);
            })

        mapData() {
            // function stuff to format data
        }

Now, I need to combine the results from the apiService with the results from this.content. The apiService returns a JSON object with a similar structure as this.content, but it comes from a third party API. I tried using flatMap to achieve this but encountered some syntax errors. My attempt looked like this:

this.content = this.http.get('src/i18n/' + this.userLang + '.json')
            .map((res:Response) => {
                let json: {} = res.json();
                return mapData(json);
            })
            .flatMap(() => {
                apiService.getAllCurrentListings().subscribe(response => {
                    return mapData(response);
                })
            });

This approach led to an error, indicating that there was a mistake in my syntax. When I call my API service outside the flatMap function, it works fine. So, clearly, I am missing something in the way I'm trying to add the apiService data to the original this.content results. Can someone help me understand how to do this correctly?

Thank you for your assistance.

Answer №1

Here is the solution that I have devised:

this.data = Observable.forkJoin(
            this.http.get('src/i18n/en.json').map((response:Response) => response.json()),
            apiService.fetchAllCurrentListings()
        ).map(result => {
            let mergedData:{} = Object.assign(result[0], result[1]);
            return processMergedData(mergedData);
        })

Answer №2

What type of data is expected to be stored in this content?

In your code, you are fetching an observable from this.http.get. In order to retrieve the data response from the http request, you should follow these steps.

Injectable()
export class ContentService {

    constructor(private http:Http, private apiService:ApiService)     {

        his.http.get('src/i18n/en.json')
            .map((res:Response) => {
                let json: {} = res.json();
                return mapData(json);
            })
            .subscribe(mappedData => 
                      this.content = mappedData)

        mapData() {
            // function stuff to format data
        }
    }      

Based on that, it seems like there might be an issue with your second snippet as well. In this particular scenario, using the flatMap operator may not be necessary since apiService.getAllCurrentListings doesn't rely on the first http call. Therefore, the forkJoin operator could offer a solution.

import {Observable} from 'rxjs/Observable'

Observable.forkJoin([
  this.http.get('src/i18n/' + this.userLang + '.json'),
  this.apiService.getAllCurrentListings()])
  .map(res => {
    this.content = this.mapData(res[0].json())
    /* once again, it's unclear what this.content should hold, but we need a separate variable for the second result */
    this.content2 = this.mapData(res[1].json())
  })
  

The .forkJoin method organizes n Observables into an array structure, requiring each response to be accessed using the appropriate array index.

If this approach doesn't align with your requirements, please specify the definition of this.content and its intended purpose.

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

How can I display and link a base64 string to an Image as a source in Nativescript?

I'm having trouble displaying and binding a base64 image as an ImageSource in my View. The image doesn't show up at all, and I couldn't find any helpful information about it in the documentation. Am I missing something? The imageSource prop ...

Displaying an Array in HTML using Angular

Just starting out with Angular and experimenting with data display from an array. The data in the array is: [Me, Three, Four] I attempted to loop through it for printing but encountered issues. Here's a snippet of how I'm currently handling it: ...

Incorporate a JavaScript array into a TypeScript document

Having a file named array.js with a large collection of strings, structured like this: module.exports = ["word1","word2",...] I attempted to utilize this array in my validation.ts file by adding the following line: let wiki = require('./array.js&a ...

Can anyone provide a solution for fixing TypeScript/React error code TS7053?

I encountered an error message with code TS7053 which states: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ name: string; isLandlocked: boolean; }'. No index signa ...

Nuxt - asyncData ISSUE: "Variable '$axios' is inferred to have an 'any' type."

Referencing the guidelines provided at Encountering an error logged in console while executing yarn dev: ERROR ERROR in pages/index.vue:51:21 ...

Develop an rxjs pipeline that merges values according to their type prior to executing them in an async manner using concatMap

In my code, there's an eventStream that deals with different types of events and sends them to the server via HTTP. import { from, Observable } from 'rxjs'; import { concatMap } from 'rxjs/operators'; type Update = number[]; inte ...

Building state from multiple child components in Next.js/React: Best Practices

To better illustrate this concept, I suggest checking out this codesandbox link. This is a follow-up to my previous question on Stack Overflow, which can provide additional context. Currently, when interacting with the child elements (such as inputs), th ...

Having trouble launching the application in NX monorepo due to a reading error of undefined value (specifically trying to read 'projects')

In my NX monorepo, I had a project called grocery-shop that used nestjs as the backend API. Wanting to add a frontend, I introduced React to the project. However, after creating a new project within the monorepo using nx g @nrwl/react:app grocery-shop-weba ...

Having trouble logging in with Google using React, Redux, and Typescript - encountered an error when attempting to sign in

As a beginner in TS, Redux, and React, I am attempting to incorporate Google Auth into my project. The code seems functional, but upon trying to login, an error appears in the console stating "Login failed." What adjustments should be made to resolve thi ...

Is there a faster way to create a typescript constructor that uses named parameters?

import { Model } from "../../../lib/db/Model"; export enum EUserRole { admin, teacher, user, } export class UserModel extends Model { name: string; phoneNo: number; role: EUserRole; createdAt: Date; constructor({ name, p ...

What is the best way to send props (or a comparable value) to the {children} component within RootLayout when using the app router in Next.js

As I work on updating an e-commerce website's shopping cart to Next.js 13+, I refer back to an old tutorial for guidance. In the previous version of the tutorial, the _app.ts file utilized page routing with the following code snippet: return ( < ...

Dynamically adjust the label position based on the button position

I am currently developing an interface that allows users to change the position of buttons and add a label text under the button. However, I am facing an issue where the label is not always centered below the button due to variations in the size and number ...

Utilize generic typings to interact with the Array object

I'm facing a challenge in developing an interface that is dependent on another interface. Everything was going smoothly until I reached the Array of Objects. Let me elaborate, I have an 'Entity' that defines how a document is stored in a ...

Guide to updating the background color of a div when clicked using Angular 6

Here is the markup: <mat-card class="example-card" *ngFor="let filteredScreen of filteredScreens" let i = index > <mat-card-header> <div mat-card-avatar class="example-header-image" > <img mat- ...

When it comes to rendering components in React using multiple ternary `if-else` statements, the question arises: How can I properly "end" or "close" the ternary statement?

I have developed a straightforward component that displays a colored tag on my HTML: import React, {Component} from 'react'; import "./styles.scss"; interface ColorTagProps { tagType?: string; tagText?: string; } /** * Rende ...

Is there a way to incorporate new members into a pre-existing type in TypeScript?

While examining the definition file for the commander project, one can observe the following interface being utilized: interface IExportedCommand extends ICommand { Command: commander.ICommandStatic; Option: commander.IOptionStatic; [key: stri ...

Learn how to navigate to a different page in Angular 4 using a button click

I'm trying to set up a button in my home.component.html page that will redirect the URL to a new page when clicked. My expectation is that clicking the button will change the current URL from http://localhost:24282/home to http://localhost:24282/mast ...

Accessing the Parent Variable from a Function in JavaScript: A Guide

How can you properly retrieve the value of x? let x = 5 const f = (n:number) => { let x = "Welcome"; return x * n // Referring to the first x, not the second one } Also, what is the accurate technical term for this action? ...

The npm warning indicates that there is tarball data for @angular/compiler version ~8.2.4

Whenever I try to create a project in Angular, I encounter this error. Can someone please advise me on how to fix it? I keep getting the npm WARN tarball tarball data for @angular/compiler@~8.2.4 error message. ...

Encountering an issue with the UNION operator in Typescript causes an error

Currently, I am utilizing the OR operator within Typescript to designate that a product could be of type ProductI OR CartResponseInterface.Product This is how it is structured: product: ProductI | CartResponseInterface.Product However, when attempting t ...