What is the functionality of mergeMap in handling errors?

In our unique scenario, we are dealing with a specific use case where we need to load 200 images 10 at a time. Utilizing MergeMap with concurrency in rxjs seems like the ideal approach for handling 200 HTTP requests and executing them in batches of 10. However, given that some images may fail to load without impacting our system, encountering errors has become a challenge.

The issue arises when using MergeMap, as any failure in one observable results in all other requests being canceled or blocked. Despite adding catchError statements at different levels of execution in an attempt to catch errors and return non-error observables, success has remained elusive.

Is there a way to leverage MergeMap concurrency while anticipating errors and ensuring the execution of all requests?

Here is a snippet of the code I am working with:

const limitedParallelObservableExecution = <T>(
                    listOfItems: T[],
                    observableMethod: (item: T) => Observable<unknown>,
                    maxConcurrency: number = maxParallelUploads
                ): Observable<unknown> => {
                    if (listOfItems && listOfItems.length > 0) {
                        const observableListOfItems: Observable<T> = from(listOfItems);
                        return observableListOfItems.pipe(mergeMap(observableMethod, maxConcurrency), toArray());
                    } else {
                        return of({});
                    }
                };

Here's how I execute it:

limitedParallelObservableExecution<T>(queueImages, (item) =>
                    methodReturnsObservable().pipe(
                        catchError((error) => {
                            // Catch error and returns Observable
                            return of([]);
                        })
                    )
                ).subscribe((value) => console.log('value: ', value));

Unfortunately, the final console.log statement within the subscribe block never gets printed.

EDIT: Upon further investigation, it appears that the issue lies within the 'methodReturnsObservable()' function:

downloadVehicleImage(imageId: string, width: number): Observable<any> {
        const params = objectToActualHttpParams({
            width,
            noSpinner: true
        });
... (additional content unchanged)
    }

By removing the pipe operation from the http.get call, I was able to resolve the issue. I will now proceed to debug this further to identify the root cause, thank you for the insight!

Answer №1

Your code snippet seems to be functioning well in isolation, but the issue might lie elsewhere. It's crucial for methodReturnsObservable to either complete or throw an error. If any observables don't finalize, toArray() won't produce any output.

One effective way to verify this is by implementing a timeout mechanism.

function executeLimitedParallelObservables<T, R>(
  itemsList: T[],
  observableFunction: (item: T) => Observable<R>,
  maxConcurrentCalls: number = defaultMaxConcurrency
): Observable<R[]> {

  return from(itemsList || []).pipe(
    mergeMap(
      item => observableFunction(item).pipe(
        timeout({ each: 5000 }),
        catchError(_ => EMPTY)
      ),
      maxConcurrentCalls
    ),
    toArray()
  );

}

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

Data fetched using React Query

When using React Query to fetch data, the function runs smoothly. After console.logging the 'data' variable from React Query, it prints an array of objects as expected and handles states efficiently between loading, success, error. The issue ar ...

Caught up: TypeScript not catching errors inside Promises

Currently, I am in the process of developing a SPFx WebPart using TypeScript. Within my code, there is a function dedicated to retrieving a team based on its name (the get() method also returns a promise): public getTeamChannelByName(teamId: string, cha ...

Attempting to grasp the concept of Typescript generics

I have a function defined as follows: interface ExtraModels extends Model { unknown: string } const write = async (data: ExtraModels[]) => { console.log(data[0].unknown) } This function is currently working. However, I want to modify it to: cons ...

Exploring the Latest Features: Using Angular 7 with Bootstrap Collapse for Dynamic Aria-Controls

I am currently working on creating my own component to use within an *ngFor loop. I am facing an issue where I need a unique value for my Collapse feature. Right now, when I click on the second main row in the table, the collapse feature only shows the inn ...

The @HostListener in Angular2 does not function correctly within a component that is inherited from another component

My Angular2-based client-side application has a base class: abstract class BaseClass { @HostListener('window:beforeunload') beforeUnloadHandler() { console.log('bla'); } } and two similar derived classes: @Component({ ...

Using boolean value as default input value in React

When trying to set the default value of a controlled checkbox input from my request, I encountered an error stating "Type 'boolean' is not assignable to type 'string | number | readonly string[] | undefined'". Do you have any suggestion ...

Using the <head> or <script> tag within my custom AngularJS2 component in ng2

When I first initiate index.html in AngularJS2, the structure looks something like this: <!doctype html> <html> <head> <title>demo</title> <meta name="viewport" content="width=device-width, initial-scal ...

Error in Subscribing to Angular 8 Async Pipe

Check out this Full StackBlitz example: https://stackblitz.com/edit/angular8-async-pipe The app component template contains three identical components: <app-loader></app-loader> <app-progress></app-progress> <app-spinner>< ...

Evaluating an angular component with a unique custom form control integrated?

My Angular component is quite simple and looks like this: import { Component, Input, forwardRef, ViewEncapsulation } from "@angular/core"; import { NG_VALUE_ACCESSOR, ControlValueAccessor } from "@angular/forms"; export const ...

I am interested in deploying an ASP.Net MVC application within the virtual directory of an existing Angular 6 application

Currently, I am working on an Angular website where I am attempting to deploy an ASP.NET MVC application within a virtual directory. However, I have encountered an issue where accessing the ASP.NET MVC application inside the virtual directory results in a ...

What could be the reason for the HttpEventType.UploadProgress event only triggering once during an Angular file upload request?

I am currently working on implementing file uploads in Angular and am looking to display the upload progress as well. upload.service.ts public uploadProductImage(obj: FormData, id: string) { return this._http.post(baseUrl + `/product/upload`, obj, { ...

Issue with Bootstrap 4 column width when using Angular 2 *ngFor

I have a container that displays search results. The layout is set up using Bootstrap columns, but there seems to be excessive padding or margin causing the results to appear very narrow. Interestingly, if I manually input each result instead of using *ngF ...

limit the data types of values within an object using Typescript

When working with typescript, how can I define the type signature for a plain old javascript object that allows any key, but restricts the values to strings only? For example, {a:"foo"} and {b:"bar"} are considered valid values, while {a:[1,2,3]} and {b:3} ...

Error message TS2339: The method 'findAll' is not defined in the current context

Despite following the Sequelize guide for TypeScript configuration, I am unable to resolve an issue with my database connection. The connection is active, but I am struggling with a specific type problem: TSError: ⨯ Unable to compile TypeScript: controll ...

Is it possible to remove generic T in typescript if the mysql result value is an array but generic T is not an array?

type User = { name: string email: string } This is the code snippet, import type { PoolConnection, RowDataPacket, OkPacket } from "mysql2/promise"; type dbDefaults = RowDataPacket[] | RowDataPacket[][] | OkPacket | OkPacket[]; type dbQuery& ...

What steps do I need to take in order to ensure that each webpage displays unique thumbnails?

As a newcomer to website development, I recently looked into implementing open graph on my site. However, I ran into an issue where I could only set one thumbnail for the entire website. This posed a problem as I wanted each navigation menu tab (Home, Abou ...

ngFor filter for converting strings to lowercase

In my application, I am implementing a pipes example that converts uppercase strings to lowercase. For example, 'Activities' becomes 'activities'. The data is in Array format, and I am using this filter with *ngFor. However, I am encoun ...

Task ':processDebugGoogleServices' could not be added because there is already a task with the same name

Trying to test out the firebase FCM plugin, but encountering numerous errors along the way. After resolving most of them, I attempted to perform the following command: ionic cordova build android, only to be faced with the following error: Here's wha ...

Encountering a problem with ResolverFactory injection while trying to inject a resolver

As a newcomer to programming, I decided to create my own Resolver class and integrate it into my feature module. However, I encountered the following error message: core.js:4352 ERROR Error: Uncaught (in promise): NullInjectorError: R3InjectorError(CivilSt ...

Tips for concealing routes in the address bar on Angular versions 5 and above

Is it possible to conceal routes from the browser's address bar? Example: http://localhost:4200/user/profile to http://localhost:4200 Is there a way to hide routes? ...