Convert information into an Observable

I have a scenario where I am fetching a list of items from an Observable in my Angular service. Each item contains an array of subjects, and for each subject, I need to make a separate API call to retrieve its details such as name, description, etc.

Data structure:

- post1
  - subjects: ['books', 'cars', 'movies']

While I have the IDs of all the subjects, I require an observable that provides me with all subjects linked to that particular post along with their respective details.

AppService.ts

getPost(id: string): Observable<Post> {
    return Observable.of({id: id, subjects: ['books', 'cars', 'movies']});
}

getSubjects(id: string): Observable<Subject[]> {
    return this.getPost(id).pipe(
        map((post: Post) => post.subjects),
        mergeMap((subjects: string[]) => subjects.map((id: string) => this.getSubject(id))),
        switchMap(list => list),
    );
}

getSubject(id: string): Observable<Subject> {
    switch (id) {
        case 'books':
            return Observable.of({id: 'books', name: 'Books'});
        case 'cars':
            return Observable.of({id: 'cars', name: 'Cars'});
        case 'movies':
            return Observable.of({id: 'movies', name: 'Movies'});
    }
}

The current implementation returns a stream of objects, but I aim to modify it to return an array containing all subjects.

[DEMO]

Answer №1

One reason for the confusion is mixing up the .map() method of Observables.map() and the .map() function of Array.prototype.map().

In the code snippet below:

 mergeMap((subjects: string[]) => subjects.map((id: string) => this.getSubject(id)))

The issue lies in returning an array of Observables instead of Subjects, as the input to the map function is an array, not an Observable. This leads to returning an array of the return type of this.getSubject(id), which are Observables.

To ensure all Observables are resolved into an array of Subjects, you need to utilize Observable.forkJoin. Using .forkJoin() combines and fires all observables in parallel.

getSubjects(id: string): Observable<Subject[]> {
    return this.getPost(id).pipe(
        map((post: Post) => post.subjects),
        mergeMap((subjects: string[]) => Observable.forkJoin([...subjects.map((id: string) => this.getSubject(id))])),
    );
}

You can then use it in your component like so:

getSubjects(id).subscribe(values=>{
    console.log(values)//returns an array of Subjects
})

Keep in mind that Observables.forkJoin will wait for all observables to complete before emitting a value.

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

Iterate through JSON objects

Having an issue with looping through JSON using jQuery AJAX. Despite receiving the JSON data from PHP and converting it to a string, I'm unable to loop through it properly in JavaScript. In my for loop, I need to access $htmlvalue[i] to parse the data ...

Using TypeScript and controllerAs with $rootScope

I am currently developing an application using Angular 1 and Typescript. Here is the code snippet for my Login Controller: module TheHub { /** * Controller for the login page. */ export class LoginController { static $inject = [ ...

The battle of efficiency: Generating content from JSON files compared to pulling from a

Greetings, fellow forum members! This is my inaugural post here. Despite the title possibly hinting at duplication, I have come across similar posts such as: one, two, three, four, and so on. However, my query bears a slight variation. I am currently in th ...

What is the best way to display all the properties of an npm package in an aesthetically pleasing format?

My curiosity leads me to explore the various methods and properties of components like GoogleMapReact. I attempted the following code: import GoogleMapReact from 'google-map-react' console.log(GoogleMapReact); However, the output is a long, mess ...

Cease the loading of a script in an HTML file

I have encountered a challenge in preventing a script from loading on my Wordpress website. The HTML file contains two scripts: <script type="0f1a6d7ca503db410c0d10c4-text/javascript" src='https://www.[-----------].se/wp-content/plugins/ ...

Vuetify Error - "Attempting to access 'extend' property of an undefined object"

Upon installing Vuetify, I encountered an error in the console. My webpack version is v3.6 Uncaught TypeError: Cannot read property 'extend' of undefined at Module../src/mixins/themeable/index.ts (index.ts:21) at __webpack_require__ (boo ...

Learn how to collapse a collapsible section in Jquery Mobile by clicking on a link. Check out the example on JSFiddle

Is there a way to make the data-role collapsible collapse when clicking a tab link? I've tried using an on-click function without success. Any ideas or alternative solutions? Thanks. Check out my JSFiddle, where you can see that the tabs change but t ...

Is it possible to launch a React application with a specific Redux state preloaded?

Is there a way to skip navigating through a bulky frontend application in order to reach the specific component I want to modify? I'm curious if it's feasible to save the redux store and refresh my application after every code alteration using t ...

The issue of Angular 4 Firebase Observable with .map() being duplicated upon refresh persists and reverting the order is not working

Utilizing Angular 4 alongside Firebase and AngularFire presents a question. How can I showcase the top 10 users from my database on the HTML code? Here is the snippet of code: export class HomefillerComponent implements OnInit { topusers: Observable< ...

Send information to modal using Javascript

I am facing an issue when trying to transfer data from JavaScript to a Bootstrap modal. Here is how my code looks: Modal: <div id="myModal" class="modal fade"> <div class="modal-dialog"> <div class="modal-content"> ...

Unable to disable webpack HMR

I have set up my project using express version 4.14.0, webpack version 1.14.0 with babel and its presets. I obtained this sample webpack configuration from a reliable source: var path = require('path'); module.exports = { entry: './main. ...

The functionality of AC_FL_RunContent is failing after an UpdatePanel postback

In the code for the repeater item, I have a JavaScript function that calls AC_FL_RunContent to display a flash file when a link within the repeater item is clicked. The datasource I am using displays the first page of video links with five items per page, ...

Angular: Error when TypeScript object returns an array object value

I have encountered a strange issue where the array value returned as [object Set] when I console log it. It's unclear whether this problem is occurring in the component or the service, but the object values are not being displayed. This issue arises ...

Accept only requests from my Chrome extension

I have successfully set up a NodeJS server with Express on DigitalOcean. My Chrome extension is able to make GET calls to the server without any issues. However, I am looking to enhance the security of the middleware below: // Add headers app.use(function ...

What is the abbreviation for a 'nested' type within a class in TypeScript?

Consider the TypeScript module below: namespace AnotherVeryLongNamespace { export type SomeTypeUsedLater = (a: string, b: number) => Promise<Array<boolean>>; export type SomeOtherTypeUsedLater = { c: SomeTypeUsedLater, d: number }; } cl ...

Transferring a picture from a computer to a Fabric.JS Canvas

Seeking Fabric.JS Experts! I've conducted thorough research but I'm struggling to find a clear explanation on how to add an image to the fabric.JS canvas. User Journey: a) User uploads an image using an input file type button. b) Once they sel ...

Generate a collection of items through replication

Develop a function that takes specific input and generates an array of objects with a length of 10 by incrementing the ID of each duplicate object. The first object in the output array should have "visible" set to true, while all others should have it set ...

Is it possible to trigger JavaScript after loading a page in jqTouch with AJAX?

Similar to the kitchensink demo, I have successfully used jqtouch to call external .html pages into the index page. One of these external pages contains a video that is being played using sublime player. Everything is pretty basic so far, but my challenge ...

What is the best way to include quotation marks in the RequestBody when sending a string?

Here is the API-method in question: @PatchMapping("/{id}") public ResponseEntity<?> partialProjectUpdate(@PathVariable long id, @RequestBody EntryStatus status) throws DailyEntryNotFoundException { return dailyEntryService.partialDailyEntryUpd ...

Unexpected checkbox behavior in buefy framework

When I create a list of checkboxes from an array, the behavior I'm experiencing is that when I select one item, it replaces the existing selection instead of adding to it. For example, if I have "Cat", "Dog" and "Bird" as options and I check "Cat", th ...