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

Using React to Identify the Chosen Option on a Custom Toggle Button

I have successfully implemented a toggle switch using HTML and CSS in my React app. I am now looking for a way to detect the selected option whenever it changes. For instance, if OR is chosen, I would like it to be saved in the selectedOption state, and if ...

Limit Typescript decorator usage to functions that return either void or Promise<void>

I've been working on developing a decorator that is specifically designed for methods of type void or Promise<void>. class TestClass { // compiles successfully @Example() test() {} // should compile, but doesn't @Example() asyn ...

Using TypeScript to deserialize JSON into a Discriminated Union

Consider the following Typescript code snippet: class Excel { Password: string; Sheet: number; } class Csv { Separator: string; Encoding: string; } type FileType = Excel | Csv let input = '{"Separator": ",", "Encoding": "UTF-8"}&ap ...

Only 1 argument was provided instead of the expected 2 when attempting to update Firebase through Ionic

I encountered an issue while trying to update Firebase from Ionic. Below is the function I used to update the data. Below is the TypeScript code: updateLaporan() { this.id = this.fire.auth.currentUser.uid; this.db.list('/laporan/'+thi ...

Error: The React component throws a TypeError because it is unable to read the property 'map' from an undefined source

I encountered the following error TypeError: Cannot read property 'map' of undefined at ListItemFactory.ts:84:57 at The specific line where the error occurs is: return announcementitems=json.value.map((v,i)=>( To provide mor ...

Extract a selection from a dropdown menu in ReactJS

I have multiple cards displayed on my screen, each showing either "Popular", "Latest", or "Old". These values are retrieved from the backend. I have successfully implemented a filter option to sort these cards based on popularity, age, etc. However, I am u ...

Error in TypeScript code for combined Slider and Input onChange functionality within a Material-UI component

HandleChange function is used to update the useState for Material-UI <Slider /> and <Input />. Here is the solution: const handleChange = (event: Event, newValue: number | number[]) => { const inputValue = (event.target as HTMLInputEle ...

How can I limit the input of string values from a Node Express request query?

export type TodoRequest = { order?: 'asc' | 'desc' | undefined; } export const parseTodoRequest = (requestData: ParsedQs): TodoRequest => { return { order: requestData.order as 'asc' | 'desc' | u ...

Transferring an array of data across different screens within an Ionic 2 application

I am a newcomer to Ionic 2 and I am encountering difficulties when it comes to passing data between pages. Within my Home.ts file, there exists a global array containing certain numbers that have been calculated. My intention is to transfer this array to m ...

Error in AngularJS and TypeScript: Property 'module' is undefined and cannot be read

I'm attempting to incorporate TypeScript into my AngularJS 1.x application. Currently, my application utilizes Webpack as a module loader. I configured it to handle the TypeScript compilation by renaming all *.js source files to *.ts, and managed to ...

Can you explain the distinction between using keyof within an indexer versus outside of it?

Consider the TypeScript snippet below: type ForwardVal<T> = { [K in keyof T]: string; }; type ForwardKeyOf<T extends string | number | symbol> = { [K in T]: string; }; type ByObj = ForwardVal<number[]>; // string[] ...

What is the best way to delete previously entered characters in the "confirm password" field after editing the password

Is there a way to automatically remove characters in the confirm password field if characters are removed from the password field? Currently, when characters are entered into the password field, characters can also be entered into the confirm password fiel ...

include choices to .vue document

When looking at Vue documentation, you may come across code like this: var vm = new Vue({ el: '#example', data: { message: 'Hello' }, template: `<div> {{ message }} </div>`, methods: { reverseM ...

What is the reason behind In-memory-web-api not generating an ID?

While I have successfully implemented the GET, PUT, and DELETE methods using InMemoryDbService to simulate an API, I am facing issues with the CREATE method. It seems like the ID is not being generated in the route to display my add form. The error message ...

Accessing information independent of Observable data in TypeScript

When attempting to send an HttpRequest in Typescript, I encountered an issue where the received data could not be stored outside of the subscribe function. Despite successfully saving the data within the subscribe block and being able to access it there, ...

Switching between various components based on conditions within the same route in Angular

My goal is to have 2 separate views, one for the homepage and another for authentication. I want to display the LoginComponent on the route '/' and the SignupComponent on the route '/signup' if the user is not logged in, otherwise rende ...

JavaScript Equivalent of Declaration in TypeScript

In my Next JS application, I encountered a situation where a line of code relies on a variable from a script src in the app.tsx page. Here's how it looks: app.tsx: <script src="https://js.stripe.com/v3/"></script> config.ts: de ...

Tips for maintaining the selection when switching pages with smart-table?

I have implemented smart-table in my project to allow users to select records from different pages and view them in a preview section. However, I am facing an issue where the selection made on the first page does not persist when navigating back to it aft ...

Encountering an issue when trying to upload a photo from Angular 8 to Laravel: receiving a "Call to a member function extension() on null" error

In my project using Angular 8 for the front end and Laravel 5.8 for the backend, I encountered an issue with uploading photos. I found guidance in this tutorial from ACADE MIND. Here is my template code : <input *ngIf="photoEdit" enctype="multipart/ ...

Angular2's ngControl is unable to retrieve default values

I have been working on a form using Angular 2 (RC.3) and noticed that the `ngForm` directive is not recognizing default values set with the `value` attribute. // app.component.html <form (ngSubmit)="onSubmit(editForm.value)" #editForm="ngForm"> &l ...