What is the best way to merge three or more Observables together?

I have obtained 3 different Observables from 3 separate Services through API calls:

this.gs.getLocationName().subscribe((loc) => this.locationName = loc);
this.gs.getLocationInfo(this.locationName).subscribe((data) => {
    this.lat = data.results.geometry.location.lat;
    this.lon = data.results.geometry.location.lng;
});
this.ws.getWeatherByCoordinates(this.lat, this.lon).subscribe((data) => ...);

Since each Observable depends on the previous one, I need to run them sequentially.

I understand how to combine 2 Observables using a pipe and mergeMap, but I face a challenge with 3 Observables.

My workaround looks like this:

this.gs
      .getLocationName()
      .pipe(
        tap((loc) => {
          this.locationName = loc;
        }),
        mergeMap((loc) => {
          return this.gs.getLocationInfo(this.locationName);
        })
      )
      .pipe(
        tap((data) => {
          this.lat = data.results[0].geometry.location.lat;
          this.lon = data.results[0].geometry.location.lng;
        })
      )
      .subscribe((data) => {
        this.ws.getWeatherByCoordinates(this.lat, this.lon).subscribe((data) => ...);
      });

While this solution works, I am uncertain about having a Subscription within another Subscription. My alternate approach is:

this.gs
      .getLocationName()
      .pipe(
        tap((loc) => {
          this.locationName = loc;
        }),
        mergeMap((loc) => {
          return this.gs.getLocationInfo(this.locationName);
        })
      )
      .pipe(
        tap((data) => {
          this.lat = data.results[0].geometry.location.lat;
          this.lon = data.results[0].geometry.location.lng;
        }),
        concatMap((data) => {
          return this.ws.getWeatherByCoordinates(this.lat, this.lon);
        })
      )
      .subscribe((data: WeatherModel) => {
        ...
      });

Although this also functions correctly, I question if it's the optimal implementation. Despite that, concatMap seems to serve its purpose for me.

Are there any recommendations on enhancing the quality of my code?

Answer №1

You're on the right track with using mergeMap. Remember, you can use mergeMap with multiple Observables.

this.gs.getLocationName().pipe(
  tap(loc => this.locationName = loc),
  mergeMap(locationName => this.gs.getLocationInfo(locationName)),
  tap(data => {
    this.lat = data.results.geometry.location.lat;
    this.lon = data.results.geometry.location.lng;
  }),
  mergeMap(data => this.ws.getWeatherByCoordinates(this.lat, this.lon))
).subscribe((data) => {
  ...
});

Additionally, if you won't be using the properties locationName, lat, and lon, you can simplify the code like this:

this.gs.getLocationName().pipe(
  mergeMap(loc => this.gs.getLocationInfo(locationName)),
  map(data => ({
    lat: data.results.geometry.location.lat,
    lon: data.results.geometry.location.lng
  })),
  mergeMap(({lat, lon}) => this.ws.getWeatherByCoordinates(lat, lon))
).subscribe((data) => {
  ...
});

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

Passing data between multiple components in Vue.js and Laravel: Best practices

require('./bootstrap'); window.Vue = require('vue'); Vue.component('exampleComponent1', require('./components/exampleComponent1.vue')); Vue.component('exampleComponent2', require('./components/exampl ...

Exploring the Utilization of FormData and form.serialize within the Data Parameter of Ajax Jquery

My form includes a multiupload uploader for files, structured like this : <div class="col-md-4"> <div class="form-group"> <label class="control-label col-md-3">Location</label> <div class="col-md-9"> <?php ...

Highly Transferable Angular Modules for 'ng-cli'

I am managing a system with multiple Angular applications built using the ng-cli: FrontendLibs @company/ core/ src/ package.json index.ts main-app/ src/ package.json In this scenario, I have two Angular applications name ...

Encountering the error message "Uncaught Promise (SyntaxError): Unexpected end of JSON input"

Below is the code snippet I am using: const userIds: string[] = [ // Squall '226618912320520192', // Tofu '249855890381996032', // Alex '343201768668266496', // Jeremy '75468123623614066 ...

How come I'm encountering issues when trying to click on the "register-selection" button in my Bootstrap and JS setup?

I am facing a challenge while developing my website. I want to trigger an alert when the "register-selection" is clicked, but despite trying both Jquery and vanilla Javascript, I have not been successful. Even after searching online resources and ChatGPT f ...

Converting TypeScript to JavaScript in a React JS application: Steps and best practices

As a beginner in the world of React, I am currently struggling with transitioning from TypeScript to JavaScript The code snippet below demonstrates the use of table filter with TypeScript. How can I adapt this code to utilize JavaScript instead? Click he ...

When the open button is clicked, the Div will toggle between open and closed states

Recently, some of my questions have not been well-received, which makes me feel a bit disheartened. It's important to remember to be kind when providing feedback. I've noticed that some people downvote without offering constructive criticism, whi ...

Using AJAX to send data to the server in jQuery

Currently, I have an AJAX request implemented on my webpage. I am exploring methods to detect when an AJAX call is initiated within the page using jQuery or JavaScript. Is there a way to identify or trigger a function upon the initiation of an AJAX reques ...

Conduct surveillance on the service function call within the constructor

I am currently facing a challenge with trying to monitor a service function call that is executed in the constructor. The test is straightforward, simply aiming to confirm that the function call is indeed made. beforeEach(async(() => { TestBed.con ...

Determine the angle needed to rotate a point in order to align it with another point in three-dimensional space

Given two vectors: V1 = { x: 3.296372727813439, y: -14.497928014719344, z: 12.004105246875968 } V2 = { x: 2.3652551657790695, y: -16.732085083053185, z: 8.945905454164146 } How can I determine the angle at which V1 needs to be rotated in order to face d ...

Error: WebView element type is not valid. A valid string was expected

Here is my basic React code : import React from "react"; import { Text, StyleSheet,View } from "react-native"; import { WebView } from 'react-native'; const App = () => { return( <WebView source={{ ...

Using a different method to handle multiple callbacks in Angular or a suitable replacement for $.Callbacks

Is there a similar functionality in Angular to jQuery $.Callbacks? I am seeking a straightforward method to manage callback lists within Angular. My goal is to achieve the following using Angular: function Broadcast(){ var self= this; this._status ...

Is there a way to stop vue-panZoom from functioning temporarily?

I am working with a Grid that includes the use of vue-panZoom. Within the Grid, there is a section that utilizes vue-draggable-resizable, similar to what is depicted in the image below: Image When I drag the gray square (vue-draggable-resizable), the bl ...

Error message: Next.js - Unable to access properties of an undefined object (user)

I am currently utilizing Next.js and Next-auth in my current project. Within this project, I am working on creating a Sidebar component that will display a list of items specific to each user. To achieve this, I am using the useSession hook to retrieve t ...

Tips for converting HTML content into a properly formatted text file

I have a user interface where users can perform various actions using ajax calls. Once the ajax call is completed, the results are displayed in a div with an id = "log". I want to provide users with an option (a button labeled Export) so that when they hav ...

How to Utilize JQuery for Sticky Elements

I am experimenting with a unique twist on the classic Sticky Element concept. Check out for a typical sticky element example. Instead of the traditional sticky behavior, I am looking to have an element initially anchored to the bottom of the user's ...

How can I locate the element immediately preceding $(this)?

Struggling to retrieve the value of the $(.subname) when the .bigadminbutton is clicked and calling the updateSub() function. I have tried various methods like prev, sibling, parent, children, find, but none seem to work. This minor task is taking up too ...

What could be the reason for my mongoose model failing to save in mongodb?

I am experiencing an issue with my simple Post model and route for creating posts. After submitting a new post using Postman, the request hangs for a moment before returning an error in JSON format. The model data is never saved successfully. Below is the ...

leveraging the useReducer hook with the possibility of dispatching actions

I am seeking assistance in adding types to a reducer function that includes optional dispatch. Below is the source of the pattern: https://twitter.com/FernandoTheRojo/status/1521312171262681090?s=20&t=oerzPqJ8cb5Ts3sHVMH_5Q Here is the code snippet: [ ...

Converting a ref or div to an Excel format using JavaScript or jQuery

I am facing an issue with exporting multiple tables to Excel in a React project. The main problem is that when I try to export the tables using libraries like "react-html-table-to-excel-3", only the first table gets exported and not the nested table insi ...