RXJS: Introducing a functionality in Observable for deferred execution of a function upon subscription

Implementing a Custom Function in Observable for Subscribers (defer)

I have created an Observable using event streams, specifically Bluetooth notifications.

My goal is to execute a function (startNotifictions) only when the Observable has a subscriber.

This piece of code used to work on previous versions with Ionic3 framework. It introduced a new operator that would run when subscribed. However, now there are type errors popping up, complaining about the absence of .doOnSubscribe on typedef Observable any> and <{}>.

Does anyone know how to correct this typing issue? Perhaps through extension? I attempted to utilize .defer directly, but it didn't work.

 // add operator doOnSubscribe to the event observable
        Observable.prototype.doOnSubscribe = function(onSubscribe) {
            let source = this;
            return Observable.defer(() => {
                onSubscribe();
                return source;
            });
        };

        // return the Observable for the notify char, with startNotify on first subscribe
        getUartDataNote( Observable.fromEvent( this.uartChar, 'characteristicvaluechanged' )
            .doOnSubscribe(() => {
                console.log('starting note');
                this.uartChar.startNotifications();
            })
            .map( value => String.fromCharCode.apply( null, new Uint8Array( this.uartChar.value.buffer )))
            .takeUntil( Observable.fromEvent( this.gatt.device, 'gattserverdisconnected' ))
            .finally(() => {
                console.log( 'stream disconnected ');
                // not necessary: return this.uartChar.stopNotifications()
            })
            .share()
        );

Answer №1

In the context of version 5 of rxjs, one can opt for implementing doOnSubscribe through pure functions rather than modifying the prototype. By doing so, it eliminates the necessity for type augmentation.

import {defer} from 'rxjs/observable/defer';
import {Observable} from 'rxjs/Observable';

/** Example
import {from} from 'rxjs/observable/from';

from([1, 2, 3])
    .pipe(doOnSubscribe(() => console.log('subscribed to stream')))
    .subscribe(x => console.log(x), null, () => console.log('completed'));
*/

export function doOnSubscribe<T>(onSubscribe: () => void): (source: Observable<T>) =>  Observable<T> {
    return function inner(source: Observable<T>): Observable<T> {
        return defer(() => {
          onSubscribe();

          return source;
        });
    };
}

https://gist.github.com/evxn/750702f7c8e8d5a32c7b53167fe14d8d

Answer №2

Learn how to enhance type definitions through augmentation here.

export {}

declare module 'rxjs/Observable' {
  interface Observable<T> {
    addNewMethod(newMethod: () => void): this;
  }
}

You can find more information on this topic in the Declaration Merging section of TypeScript's handbook.

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

Exploring the wonders of Angular 2: Leveraging NgbModal for transclusion within

If I have a modal template structured like this: <div class="modal-header"> <h3 [innerHtml]="header"></h3> </div> <div class="modal-body"> <ng-content></ng-content> </div> <div class="modal-footer"& ...

Processing HTTP requests routed from Firebase Hosting to Cloud Functions

I'm currently working on integrating data patching with my Firestore database using http. My goal is to achieve this without relying on an external server, by utilizing Firebase Hosting and Functions. Firstly, I set up my Firebase project and importe ...

How to leverage tsconfig paths in Angular libraries?

While developing an Angular library, I made configurations in the tsconfig.lib.json file by adding the following setup for paths: "compilerOptions": { "outDir": "../../out-tsc/lib", "target": "es2015", "declaration": true, "inlineSources ...

Error: Loki cannot be used as a constructor

Can anyone assist me in understanding why this code is not functioning correctly? Here's what my index.ts file in Hapi.js looks like: import { Server, Request, ResponseToolkit } from '@hapi/hapi'; import * as Loki from 'lokijs'; ...

What could be causing the table to display empty when we are passing data to the usetable function?

Visit Codesandbox to view Table While the header appears correctly, I noticed something strange. When I console log the data props, it shows all the necessary data. However, when I try to console.log row, there doesn't seem to be any single object re ...

Inversify's Http Context consistently remains void of any content

Hello there, I'm in need of assistance with building an API using inversify and inversify-express-utils. Everything seems to be working fine with my controllers and the API so far, except for one issue. When trying to access the httpContext property i ...

How can you convert all nodes of a nested JSON tree into class instances in Angular 2 using Typescript?

I have a Leaf class that I want to use to convert all nodes in a JSON response into instances of Leaf. The structure of the JSON response is as follows: JSON Response { "name":"animal", "state":false, "children":[ { "name" ...

Warning from Cytoscape.js: "The use of `label` for setting the width of a node is no longer supported. Please update your style settings for the node width." This message appears when attempting to create

I'm currently utilizing Cytoscape.js for rendering a dagre layout graph. When it comes to styling the node, I am using the property width: label in the code snippet below: const cy = cytoscape({ container: document.getElementById('cyGraph&apo ...

A step-by-step guide on integrating Azure Cognitive Search within a SharePoint Online SPFx webpart

I haven't had much experience with SPFx recently, so it looks like I'll need to brush up a bit. :) I'm interested in implementing this NPM package: https://www.npmjs.com/package/azure-search Within a simple new SPFx web part: The code ...

Importing node_modules in Angular2 using TypeScript

My Angular2 app started off as a simple 'hello world' project. However, I made the questionable decision to use different directory structures for my development environment and the final deployment folder on my spring backend. This difference c ...

Error message: "An issue has been encountered within Angular 4 where it is

Thank you for any assistance, I realize this may be a beginner question... but I seem to be missing something and my TypeScript code is error-free. My goal is simple: I want to track which Main Menu Item is currently selected. To achieve this, I have bou ...

What exactly does "tsc" stand for when I compile TypeScript using the command "(tsc greeter.ts)"?

What does tsc stand for when compiling TypeScript code? (tsc greeter.ts) tsc I'm curious about the meaning of tsc in this context. ...

The attribute 'disabled' is originally defined as a characteristic within the class 'CanColor & CanDisableRipple & HasTabIndex & MatChipBase'. However, it is replaced in the current context of 'MatChip' as an attribute

After updating my Angular version from 9.1 to 11, I encountered a compilation error. Error: node_modules/@angular/material/chips/chips.d.ts:120:9 - error TS2611:'disabled' is defined as a property in class 'CanColor & CanDisableRipple &a ...

What is the best way to hold out for a specific number of promises to be fulfilled and halt the resolution of any others

While working in TypeScript, I need to create around 100 instances of Promise. However, I am only interested in waiting for the resolution of 5 of them. Any promises beyond that can either be canceled (if feasible) or rejected since they are no longer requ ...

Struggling to locate the module in React Native with TypeScript configuration

Currently, I am in the middle of transitioning our react-native project from JavaScript to TypeScript. As I attempt to import old modules, I keep encountering the following error: Cannot find module 'numeral' Oddly enough, the 'numeral&apo ...

What is the process for generating an index.d.ts file within a yarn package?

I'm facing an issue with creating the index.d.ts file for my yarn package. Here is my configuration in tsconfig.json: { "include": ["src/**/*"], "exclude": ["node_modules", "**/*.spec.ts"], " ...

Creating custom functionality by redefining methods in Typescript

My current scenario is as follows: abstract class A implements OnInit{ ngOnInit() { this.method(); } private method() { // carrying out tasks } } class B extends class A implements OnInit { ngOnInit() { thi ...

A more concise validation function for mandatory fields

When working on an HTML application with TypeScript, I encountered a situation where I needed to build an error message for a form that had several required fields. In my TypeScript file, I created a function called hasErrors() which checks each field and ...

MUI provides the flexibility to adjust the opacity separately for Chip labels/icons and backgrounds

My objective is to customize the opacity of label/icon and background in MUI Chip. I want the label & icon to have an opacity of 1, while the background should have an opacity of 0.0571. Technologies used in this project include React, TypeScript, Materia ...

Displaying updated information in Angular

I recently developed a chat application using Angular that utilizes the stomp socket from @stomp/ng2-stompjs. To display all messages, I am leveraging *ngFor. <p *ngFor="let item of messages" style="padding: 5px; font-size: 18px"> <span style ...