How can you populate an observable with another observable and then return the resulting observable?

I am currently working on a project using rxjs and json-server as the database provider. I have encountered an issue while trying to populate one collection with another.

The two collections in question are Match and Tournament. The Match collection contains a tournamentId, but also has a Tournament instance within it.

class Match{
    id:number;
    ...
    tournamentId:number;
    tournament: Tournament;
}

class Tournament{
    id:number;
    ...
    name:String;
}

To achieve this, I need to make two separate calls to the database - one to retrieve all tournaments and another to get all the matches.

My goal is to return an Observable of Match that has been populated with the associated Tournament.

get(): Observable<Match> {
    return Observable.create(obs => {
      tournamentService.get().pipe(toArray()).subscribe(tournaments => {//tournaments = [torunament1, tournament2]
        super.get().pipe(map(x => { let m = new Match(x); m.populateTournament(tournaments); obs.next(m); return m; })).subscribe(() => {
          obs.complete();
        });
      });
    });
  }

The issue I am facing is that obs.complete() is getting called right away, resulting in only one Match being created in the observable. I am attempting to populate the Match with the Tournament in the map pipe, and then send it using obs.next(m). However, I am unsure if this approach is the most efficient.

tournamentService.get() and super.get() both return Observables of the Tournament and unpopulated Match respectively (JS {object} with the same attributes).

What would be the best way to call next() for each match individually and only call complete() once all matches have been sent to the subscriber?

Answer №1

It's recommended not to create your own observables as there are already existing operators that can be used for that purpose. MergeMap, switchMap, and combineLatest would be suitable options in this scenario.

An ideal approach would be to merge these two observables:

  fetch(): Observable<Game> {
    return combineLatest([super.fetch(), gameService.fetch()]) // Merge both Observables when they emit values
      .pipe(map(([game, services])=> { // Unpack array of emitted values
        let g = new Game(game);
        g.populateServices(services);
        return g; // Return game combined with services
    }))
  }

Answer №2

I successfully resolved the issue using the 'withLatestFrom' operator as well.

 get(): Observable<Match> {
    let matchesObs = super.get();
    let tournamentsObs = tournamentService.get().pipe(toArray());

    return matchesObs.pipe(
      withLatestFrom(tournamentsObs),
      map(([m, t]) => {
        let match = new Match(m as Match);
        match.populateTournament(t as Tournament[]);
        return match;
      })
    );
  }

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

The error "Uncaught ReferenceError: global is not defined" occurred at the location of Object./node_modules/fbjs/lib/setImmediate

While attempting to render a Button component from ant design in my Electron project, I encountered an error where nothing was being rendered. However, when I switched to just displaying 'Hello World' text, it worked without any issues. I'm ...

What is the best way to implement a late-binding clone method in TypeScript classes?

Creating a simple Cloneable interface for all my data classes in JavaScript is a straightforward task. However, when it comes to typing it properly in TypeScript, things get a bit more complex. Currently, I am putting together a solution like this: class ...

Error: Android package not found when building a NativeScript app with TypeScript

I encountered the following error message: main-page.ts(15,26): error TS2304: Cannot find name 'android'. This error occurred after setting up a new NativeScript project using TypeScript. tns create demo --template typescript I then added the ...

To set up the store in configureStore, you must provide one type argument for the 'MakeStore' generic type

Encountering an issue with MakeStore showing a Generic type error 'MakeStore' requires 1 type argument(s) .ts(2314) Here is the code from configureStore.ts: import { configureStore, EnhancedStore, getDefaultMiddleware, } from '@reduxj ...

A guide on instantly updating displayed flat/section list elements in React Native

I am in the process of creating a screen called ContactListScreen. The direct child of ContactListScreen is ContactItems, which is a sectionList responsible for rendering each individual ContactItem. However, I have encountered a problem where my ContactIt ...

Connecting the mat-progress bar to a specific project ID in a mat-table

In my Job Execution screen, there is a list of Jobs along with their status displayed. I am looking to implement an Indeterminate mat-progress bar that will be visible when a Job is executing, and it should disappear once the job status changes to stop or ...

Jest encountered an UnhandledPromiseRejection error because the promise was unexpectedly resolved instead of being rejected

I am facing a difficult error message from Jest that I can't seem to figure out. The error message indicates that the promise is being resolved instead of rejected, causing an unhandled promise rejection. It's confusing because Jest expects an er ...

In Typescript, object strings can be enforced to be used from the parent object similar to

I am currently developing an API wrapper for a lower level library that utilizes enums to map human readable keys to internal values. In order to enhance security, I want to only use the enum keys and not the underlying values in any logging or other funct ...

Having trouble getting Angular 8 WebRTC to function properly on two tabs

I've been tasked with creating an audio chat room for 2 users. Initially, I used the following app example: Peer connection: audio only After converting the code to TypeScript, it successfully ran: Stackblitz However, I'm facing challenges ge ...

What causes the oninput event to act differently in Angular as opposed to regular JavaScript?

As I delve into learning Angular with TypeScript, I've encountered some inconsistencies compared to JavaScript that are puzzling me. Take for example this function that works flawlessly with pure JavaScript, where it dynamically sets the min and max a ...

Ways to enforce a specific type based on the provided parameter

Scenario Background: // Code snippet to do validation - not the main focus. type Validate<N, S> = [S] extends [N] ? N : never; // Note that by uncommenting below line, a circular constraint will be introduced when used in validateName(). // type Val ...

How to Add a Rule to an Existing Application Load Balancer Listener using AWS CDK

When I inherited a project, I discovered an application load balancer with a HTTPS Listener that was set up before I began using CDK. This listener currently has 13 rules in place that route requests based on hostname to different fargate instances, with ...

The specified reference token grant value of [object Object] could not be located in the store

Currently, I am working with NestJs along with the oidc passport strategy using identityserver. Below is a snippet of the code: import { UnauthorizedException } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; ...

Pull in class definitions from the index.js file within the node_modules directory

In my project, I have the package called "diagram-js" in the node_modules. The file node_modules/diagram-js/lib/model/index.js contains multiple class definitions as shown below: /** * @namespace djs.model */ /** * @memberOf djs.model */ /** * The b ...

Firestore query failing to retrieve most recent data

I have implemented a route guard in Angular that validates a specific value in firestore before granting access to the designated route. The component is accessed only after an HTTP cloud function has finished executing. This cloud function generates an o ...

Adjusting the resolution of a video on repeat

I am attempting to reduce the resolution of a video to below 500x500 without compromising its quality. My approach is to decrease the resolution by 75% in a loop until it reaches the desired dimensions. While this seems simple in theory, I am struggling to ...

Adjusting the ng-turnstile Dimensions

Looking for a way to adjust the width of CloudFlare Turnstile to match its parent container's layout without causing any issues with the Iframe. Is there a more efficient method to achieve this? The current solution I have seems to be messy: import { ...

Can Vitest be configured to use a separate tsconfig file?

Can I specify a different tsconfig file for vitest? In my extensive project that is currently using vue-cli, I am considering switching to vite. However, before making the full conversion, I would like to start by using vitest instead of jest. The issue a ...

Adding images to your SVG using Bobril is a simple process that can add visual

I have been attempting to insert an image into an SVG using Bobril, but the following code is not functioning as expected: { tag: 'svg', children: { tag: 'image', attrs: { 'xlink:href': &ap ...

React's Redux persist is causing a duplication of requests being sent

I am currently utilizing redux-persist along with Redux Toolkit. I have observed a peculiar behavior where, upon changing the slice (RTK), a request is sent to the server. When using redux-persist without a persister, only one request is made as expected. ...