Alert: User is currently engaging in typing activity, utilizing a streamlined RXJS approach

In my current project, I am in the process of adding a feature that shows when a user is typing in a multi-user chat room. Despite my limited understanding of RXJS, I managed to come up with the code snippet below which satisfies the basic requirements for the "User is Typing" feature:

   this.messageForm.message.valueChanges
      .pipe(
        tap(() => this.convoService.isUserTyping(true)),
        debounceTime(500),
        map(() => this.convoService.isUserTyping(false))
      )
      .subscribe();

However, this implementation is not efficient as it sends too many requests to the server. My objective is to restrict requests to only 2, and utilize RXJS operators to achieve the following specific behaviors:

  1. Send a request on the initial keypress
  2. Disregard any subsequent keypresses
  3. Wait for a set duration after the last keypress
  4. Restart the timer if a new keypress occurs before the timer ends
  5. Send a request once the timer expires

Answer №1

Here is a method that ensures no side effects:

const userInput$ = this.messageForm.message.valueChanges.pipe(
  switchMap(() => concat(
    of(true),
    of(false).pipe(delay(500)),
  )),
  distinctUntilChanged(),
)

You can utilize this to handle your requests. If isUserTyping is a fire-and-forget task, you can simply use

userInput$.subscribe(typing => this.convoService.isUserTyping(typing));

If it involves an asynchronous operation (and returns an observable) I would suggest the following approach:

userInput$.pipe(
  concatMap(typing => this.convoService.isUserTyping(typing))
).subscribe();

This method ensures that all requests are executed in sequence, preventing any out-of-order issues especially in high-latency scenarios¹.


¹ If latency becomes a significant concern, additional measures such as buffering may be needed to prevent excessive backpressure on the requests. However, for the scope of this question, that level of detail is unnecessary.

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

What is the best way to incorporate a class creation pattern in Typescript that allows one class to dynamically extend any other class based on certain conditions?

As I develop a package, the main base class acts as a proxy for other classes with members. This base class simply accepts a parameter in its constructor and serves as a funnel for passing on one class at a time when accessed by the user. The user can spe ...

displaying post data in the URL address bar

During the development of my portal using angular 5, everything was running smoothly in the testing environment. However, due to production requirements, I made some changes to access modifiers from private to public. This modification has caused issues in ...

Using a try block inside another try block to handle various errors is a common practice in JavaScript

In an effort to efficiently debug my code and identify the location of errors, I have implemented a try-catch within a try block. Here is a snippet of the code: for (const searchUrl of savedSearchUrls) { console.log("here"); // function will get ...

ERROR: The variable countryCallingCode has not been defined

I encountered an error when attempting to assign a value to my property countryCallingCode, which does not exist in the first option. this.allData.customerFacingPhone.countryCallingCode = newItem.countryCallingCode The error message I received was: ERROR ...

Ways to manage drag and drop functionality within Cypress when traditional Cypress techniques are not effective

I need help with the drag and drop function in Cypress. I have tried three different methods but none of them seem to work. I have included my code below, which is not functioning as expected. Does anyone have any suggestions on what might work better in t ...

The sorting feature is not performing as anticipated

I'm dealing with an array of objects fetched from the backend. When mapping and sorting the data in ascending and descending order upon clicking a button, I encountered some issues with the onSort function. The problem lies in the handling of uppercas ...

Creating a type-safe method wrapper in TypeScript based on function names

Many Q&As discuss creating a function wrapper in TypeScript, but my question is how to do the same with named methods. I am interested in writing something similar to this JavaScript code: function wrap(API, fnName, fn) { const origFn = API.p ...

Challenges with Angular 4 service initialization

Having trouble with my authentication service. The constructor is being called 259 times when making an HTTP request, but only once when the call is removed. I am using a shared module to provide a unique instance of the service. Angular version: 4.4.4 C ...

Enhancing React Native View and other component properties using styled-components

Utilizing styled-components for styling in my React Native app using Typescript has been effective. I recently crafted a StyledComponent to style a View component, but encountered an error when attempting to extend the ViewProps: The type '{ children: ...

What is the best approach for designing a UI in Angular to showcase a matrix of m by n dimensions, and how should the JSON format

click here for a sneak peek of the image Imagine a matrix with dimensions m by n, containing names on both the left and top sides. Remember, each column and row must be labeled accordingly. ...

Dialog box obscuring PrimeNG dropdown menu

I'm working on an Angular2 app that utilizes PrimeNG components. My issue arises when trying to include a dropdown inside a dialog box. Despite my implementation, the dropdown ends up being cut off due to the constraints of the dialog box, as visible ...

Tips on ensuring all fields are mandatory in a form

Currently, I am in the process of working on my Angular2 project. Specifically, I have created a form and my intention is to make all fields required. However, I encountered an issue when attempting to make the Title field mandatory as it is not displaying ...

Angular 8 Refresh Token Implementation

I am currently working on an Angular 8 app that is integrated with .NET Core. My goal is to find a way to refresh a JWT token within the application. Within the integration, users are able to validate and receive a token which expires after 30 minutes. T ...

Incorporate any enum value into a Typescript interface

I'm working with a Typescript interface export interface MyInterface { valid: boolean; resourceType: MyEnum; message: string; } As well as an enum enum MyEnum { 'a', 'b', 'c' } Is there a way to allow the ...

I am confused as to why I am receiving npm warnings for angularfire 2.0.0-beta.2 when I have only been using version 2.0.0-beta.0

Currently, I am working on a project that involves using angularfire 2.0.0-beta.0 as specified in the package.json file... "angularfire2": "^2.0.0-beta.0" ...however, upon running npm install, I have been receiving npm warnings related to angularfire 2.0 ...

In a situation where Typescript fails to provide enforcement, how can you effectively indicate that a function is not defined for specific value(s)?

If I were to utilize Typescript to create a function called mean that calculates the mean of an array of numbers, how should I handle the scenario where the array is empty? Enforcing that an array must be non-empty can be inconvenient, so what would be th ...

The mat-slide-toggle component does not recognize the checked binding

My angular app contains the mat-slide-toggle functionality. switchValue: {{ switch }} <br /> <mat-slide-toggle [checked]="switch" (toggleChange)="toggle()">Toggle me!</mat-slide-toggle> </div> This is how the ...

The system encountered an error when attempting to convert the data '19-10-2002' into a date format

I am trying to pass a date parameter in the format (dd-MM-yyyy) and then convert it into the format (yyyy-MM-dd) before sending it via API. Here is my code: convert(date:string){ date //is in the format(dd-MM-yyyy) date = formatDate(date , " ...

Sliding toggle in Angular Material2 Menu

How can I properly include a Slide-toggle <mat-slide-toggle> within a Menu <mat-menu>? In addition, when I toggle the Slide-toggle, the menu closes. Is there a way to prevent this behavior? <mat-menu #menuSettings="matMenu"> ...

Having difficulty using the Angular 6 "generic type elementref requires 2 type arguments" error message in my code

When attempting to use ElementRef, I included the following import statement: import { Component, OnInit, ElementRef, ViewChild } from '@angular/core'; I followed the examples and injected it into the constructor as shown: constructor(private ...