RxJS: when combined with timer, groupBy operator does not emit any values

Just starting out with RxJS version 6.5.5, I'm encountering an issue with the groupBy operator. Here's a simplified example to showcase the problem.

I have a function called retrieveFiles() that retrieves an array of strings.

function async retrieveFiles(): Promise<string[]> {
  return ['file1.txt', 'file2.txt', 'file3.txt', 'directory1', 'directory2'];
}

In real-life scenario, this function would fetch data from a remote source.

Assuming I want to group the filenames based on the first 4 characters.

With RxJS, I can achieve this using the following code snippet.

of(retrieveFiles()).pipe(
  concatMap(v => v),
  mergeMap(value => value),
  groupBy(
    (name: string) => name.substr(0, 4),
    (name: string) => name,
  ),
  mergeMap(group$ => group$.pipe(toArray())),
)
.subscribe(console.log);

This will output two sets of values to the subscriber.

[ 'file1.txt', 'file2.txt', 'file3.txt' ]
[ 'directory1', 'directory2' ]

Now let's add in the timer and make some changes to the code. Essentially, we are now creating a polling mechanism.

timer(0, 1000)
  .pipe(
    concatMap(() => this.retrieveFiles()),
    mergeMap(value => value),
    groupBy(
      (name: string) => name.substr(0, 4),
      (name: string) => name,
    ),
    mergeMap(group$ => group$.pipe(toArray())), 
  )
  .subscribe(console.log);

Surprisingly, this doesn't produce any output. What could be the difference between these two implementations?

Answer №1

When looking at your second scenario, the key difference lies in the fact that timer never completes while of does. Additionally, toArray only emits when its source completes. However, the grouped observable from groupBy is expecting future emissions since timer serves as its source, leading to the grouped observables never completing.

If you wish for new groups to be generated for each poll, a slight restructuring is necessary to make retrieveFiles its source.

timer(0, 1000)
  .pipe(
    // It's recommended to use switchMap to prevent a hanging request from clogging your stream
    switchMap(() => from(retrieveFiles()).pipe( 
      mergeMap(value => value),
      groupBy(
        (name: string) => name.substr(0, 4),
        (name: string) => name,
      ),
      mergeMap(group$ => group$.pipe(toArray())), 
    )),
  )
  .subscribe(console.log);

This does bring up an interesting point worth discussing - whether this approach is truly beneficial. Achieving the same result can be done simply using a map operator with a synchronous array grouping function inside it instead of all the back and forth stream conversion. While exploring the library is great, in practical applications, I would advise against this. groupBy should be reserved for scenarios where you are dealing with actual streams of values that need to be grouped into separate observable streams.

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

Typescript Error:TS2345: The argument '{ theme: string; jsonFile: string; output: string; }; }' is not compatible with the parameter type 'Options'

Encountering an error mentioned in the title while using the code snippet below: import * as fs from 'fs' import { mkdirp } from 'mkdirp' import * as report from 'cucumber-html-reporter' const Cucumber = require('cucumber ...

What is the correct way to implement fetch in a React/Redux/TS application?

Currently, I am developing an application using React, Redux, and TypeScript. I have encountered an issue with Promises and TypeScript. Can you assist me in type-defining functions/Promises? An API call returns a list of post IDs like [1, 2, ..., 1000]. I ...

Missing data: null or undefined?

When using vuex-module-decorators, is it better to set the default value of a data property to null or undefined? For example: export default class ComponentName extends Vue { post: BlogPost | null = null } or export default class ComponentName extends V ...

Compiling with tsc --build compared to tsc --project

I'm currently working on converting a subproject to TypeScript within my monorepo. Within my npm scripts, I initially had: "build-proj1":"tsc --build ./proj1/tsconfig.json" Although it did work, I noticed that the process was unus ...

The RazorPay callback encountered an Uncaught TypeError indicating that the function is not recognized

In my TypeScript class, I have a defined handler as follows: "handler": function (response) { this.sendUserStatus(); }, Unfortunately, when I attempt to call this.sendUserStatus();, I encounter the following error: Uncaught Typ ...

I encountered an issue where I did not receive a response when utilizing res.write() within the fetch function

Currently, I am utilizing the <res.write()> method in nodejs at https://nodejs.org/api/http.html#responsewritechunk-encoding-callback. In addition to this, I am also implementing the fetch function which can be found at https://developer.mozilla.org/ ...

Is it possible to update duplicated records in Firestore using a cloud function when there are changes made to the document

In my Firestore setup, I have the following structure: Users / uid / following / followingPersonUid / Users / uid / followers / followerPersonUid / When User A follows User B, User A is added to the followers sub-collection of User B and User B is added ...

When changing the dropdown option on a separate page in React/Next JS, all checkboxes show the clicked style as a result of utilizing useState

I have implemented checkboxes for three different categories: "Types", "Price", and "Categories". They function correctly, with data being passed to a separate checkbox component without any issues. The problem arises when I click a checkbox and then inte ...

Linking events together to fetch interconnected information

When loading an employee in my resolver, the employee returns a list of town's ids. My goal is to load all the towns from this id list within the same resolver without returning the list of towns, but instead returning the employee object. The loaded ...

Creating a form with multiple components in Angular 6: A step-by-step guide

I'm currently working on building a Reactive Form that spans across multiple components. Here's an example of what I have: <form [formGroup]="myForm" (ngSubmit)="onSubmitted()"> <app-names></app-names> <app-address> ...

Creating a versatile JavaScript/TypeScript library

My passion lies in creating small, user-friendly TypeScript libraries that can be easily shared among my projects and with the open-source community at large. However, one major obstacle stands in my way: Time and time again, I run into issues where an NP ...

Ways to utilize array reduce for organizing information

Can someone please guide me on how to use the reduce array method to sort entries by date in the following data: const entries = [ {date: 'lu'}, {date: 'lu'}, {date: 'ma'}, {date: 'ma'} ] I would like the ou ...

Creating applications with Angular2 and TypeScript is possible even without utilizing NPM for development

I've seen all the guides recommend installing npm, but I'm determined to find an alternative method. I found Angular2 files available here, however, none of them are in TypeScript code. What is the best course of action? Do I need Angular2.ts, ...

Experiencing a useContext error when implementing MDX with NextJS 13

I am currently working on integrating mdx files into Next.js 13. After completing all necessary configurations in next.config and creating the file structure, I have the following path within the app folder: > docs > components > accordion > pa ...

Ignore one specific file when importing all files in Angular 7

In my Angular 7 project, I am utilizing C3 and importing all the necessary files at the beginning of my .ts component file using a wildcard. import * as c3 from 'c3'; While this method works well overall, I encountered an issue where my CSS ove ...

Is node.js necessary for running TypeScript?

Node.js is necessary for installing TypeScript. I believe that TypeScript utilizes Node.js to compile .ts files into .js files. My concern is whether the generated .js file needs node.js in order to function properly. From what I've observed, it seem ...

Is there a way to efficiently convert several strings within an object that has been retrieved from an HTTP request into another language, and subsequently save this object with the

Is there a way for me to translate some strings in an object before storing it in another http request using the Google Translate API? I am currently getting the object from one http request and saving it with a put method. How can this be achieved? servi ...

Adaptively linking to the property of a deeply nested object

Attempting to bind to a property of a nested object using [(ngModel)], but facing the challenge that the path to the property is dynamically set. Consider the following three classes: class A { p1: C constructor() { p1 = new C("A") } } class B { p2: ...

Convert JSON data to an array using Observable

My current task involves parsing JSON Data from an API and organizing it into separate arrays. The data is structured as follows: [ {"MONTH":9,"YEAR":2015,"SUMAMT":0}, {"MONTH":10,"YEAR":2015,"SUMAMT":11446.5}, {"MONTH":11,"YEAR":2015,"SUMAMT":5392 ...

Webpack 4.1.1 -> The configuration.module contains a property 'loaders' that is unrecognized

After updating my webpack to version 4.1.1, I encountered an error when trying to run it: The configuration object is invalid. Webpack has been initialized with a configuration that does not match the API schema. - The 'loaders' property in ...