Unlock the key to connecting the output of one observable to another in rxjs

I have a procedure for saving users in the database.

These are the steps I take:

1) First, I validate the request.

2) Next, I hash the password.

3) Finally, I store the user details in the users collection along with the hashed password.

Below is the code where I subscribe to the hashPassword method, get the hashed string, create the user with the hashed string, and then subscribe to the save method. Instead of subscribing multiple times, how can I achieve this using the zip() or map() operator?

createUser(req: Request, res: Response): Observable<mongoose.Document> {
    const body = req.body
    const self = this

    return singleObservable(Observable.create((observer: Observer<mongoose.Document>) => {
        const errorMessage = new UserValidator(req).validateRequest()
        if (errorMessage) {
            observer.error(errorMessage)
        } else {
            self.hashPassword(req.body.password).subscribe(new BaseObserver(
                (value) => {
                    const newUser = new this.userModule({ email: req.body.email, username: req.body.username, password: value })
                    this.save(newUser).subscribe(new BaseObserver((value) => {
                        observer.next(value)
                    }, (err) => {
                        observer.error(err)
                    }))
                }, (error) => observer.error(error)))
        }
    }))
}

private hashPassword(password: string): Observable<string> {
    return singleObservable(Observable.create((observer: Observer<string>) => {
        bcrypt.hash(password, 10, (err, result) => {
            result.length > 0 ? observer.next(result) : observer.error(err)
        })
    }))
}

save<T extends mongoose.Document>(model: mongoose.Document): Observable<T> {
    return singleObservable(Observable.create(function (observer: Observer<mongoose.Document>) {
        model.save(function (err, object) {
            emitResult(observer, object, err)
        })
    }))
}

emitResult<T, E>(observer: Observer<T>, result: T | null, err: E) {
    result ? observer.next(result) : observer.error(err);
}

singleObservable<T>(observable: Observable<T>) : Observable<T> {
    return observable.pipe(first())
}

Answer №1

I successfully resolved my problem by utilizing the flatMap operator

createUser(req: Request, res: Response): Observable<mongoose.Document> {
    const data = req.body
    const creator = this

    const errorMSG = new UserValidator(req).validateRequest()
    if (errorMSG) {
        return throwError(errorMSG)
    } else {
        return creator.hashPassword(req.body.password)
        .pipe(flatMap((hashedValue) => {
            const freshUser = new this.userModule({ email: req.body.email, username: req.body.username, password: hashedValue })
            return this.save(freshUser)
        }), catchError((err) => throwError(err))
    }
}

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 purpose of using 'ref' in conjunction with useCallback instead of just utilizing useCallback on its own?

While working on my React project, I came across some libraries that used 'useCallback' in a different way than I'm used to. Below is the code snippet showcasing this approach. Despite my initial thoughts, I still believe there's no sig ...

Avoid accessing invariant variables when mocking: __extends

I'm currently in the process of converting a collection of react components from JavaScript to TypeScript, and I've encountered an issue with jest.mock(). Before: "react": "^15.6.1" "jest": "20.0.4" "enzyme": "^2.9.1" CustomDate.js ... import ...

Tips for eliminating the gap between digits and symbols in an OutlinedTextField within the Material Ui framework

Using material Ui OutlinedTextField with the code snippet below import { List, styled, Switch, TextField, Theme, withStyles } from '@material-ui/core'; export const OutlinedTextField = withStyles((theme: Theme) => ({ root: { '& ...

Encountering an undefined value in Angular outside of the subscription

I am facing an issue where I need to use the value from the user outside the subscribe function in order to assign it to my tweet class. However, when I try to print it outside the subscribe function, it shows as undefined. Can anyone provide a solution fo ...

Using TypeScript to Initialize Arrays with Objects

Why is it that in TypeScript 1.8, the following code blocks with initializers are considered legal syntax: class A { public textField: string; } var instanceOfClass = new A { textField = "HELLO WORLD" }; var arrayCollection = new A[] { new A ...

Implementing pagination within an Angular 11 Mat-table with grouping feature

Encountering an interesting issue with MatTable pagination and grouping simultaneously. I have two components each with a Mat-table featuring Pagination+Grouping. ComponentOne functions smoothly without any issues. When choosing to display 5 elements pe ...

Typescript error code TS7053 occurs when an element is detected to have an implicit 'any' type due to an expression of a different type

I encountered an issue with the provided example. I'm uncertain about how to resolve it. Your assistance would be greatly appreciated. type TestValue = { value: string; }; type FirstTest = { type: 'text'; text: TestValue[]; }; typ ...

The State of NgRX Entity is encountering undefined IDs

I decided to experiment with @ngrx/entity in a simple "Todo" project, where I had only one AppModule, one reducer, and a single component. However, as I delved into it, I encountered some challenges. The actions I defined were quite basic, focusing on CRU ...

Why do ES6 classes fail to set properties when an overloaded function is called within the constructor of the parent class?

I encountered a puzzling scenario while coding that has left me perplexed. Here's the situation: I am extending a class from a library, which serves as the "Parent"-class. It allows its subclasses to override the init-method for custom initialization ...

Saving data from Material UI forms in TypeScript

Is there an effective method for storing values entered into the text fields on this page? const AddUserPage = () => ( <div> <PermanentDrawerLeft></PermanentDrawerLeft> <div className='main-content'> < ...

Implementing NestJS: Integrating TypeORM Datasource without relying on class dependency injection

I have a unique situation that requires some help. Our team is in the process of integrating nestjs into our current express codebase. Previously, we were using Typeorm 0.2 and recently upgraded to 0.3. Due to the fact that we utilize functions instead of ...

What could be the reason behind the material table not populating with data from the source, despite the service returning an array?

Currently, I am utilizing a mean stack in order to craft a bug tracking system. The issue arises when my express.js service returns an array of issues, which I assign to another array that functions as the dataSource for mat-table. However, despite the ar ...

Tips for implementing absolute import paths in a library project

In my workspace, I have a library with two projects: one for the library itself and another for a test application. ├── projects    ├── midi-app    └── midi-lib Within the workspace's tsconfig.json file, I set up paths for @a ...

What is the best way to trigger a code block once an observable in Angular has completed all of its tasks?

I have an observable made from an array of form controls in Angular. I am using dropdowns and inputs to calculate the sum of all currencies in relation to one currency, and it works. However, my issue is that when I want to update the field itself, the v ...

Unable to link to '' because it is not recognized as a valid attribute of '' in Angular 2

I encountered an exception while working on my Angular 2 project and I'm struggling to figure out the cause. Below is the snippet of my code: ts: import {Component} from "@angular/core"; import {GridOptions} from "ag-grid"; import {RedComponentComp ...

The TypeScript error "Uncaught ReferenceError: require is not defined" occurs when the

When attempting to export a namespace from one .ts file and import it into another .ts file, I encountered an error: NewMain.ts:2 Uncaught ReferenceError: require is not defined. As someone new to TypeScript, I am still in the learning process. Below is a ...

tslint: no use of namespace and module is permitted

I have recently acquired a legacy .ts file that I would like to update. Two warnings appear: 'namespace' and 'module' are disallowed and The internal 'module' syntax is deprecated, use the 'namespace' keyword ins ...

Issue with React Redux: Store dispatch not causing component update

I have recently implemented React Redux in my project, but I seem to be encountering some issues. Despite changing the state, the value remains the same. I attempted to use useStore(), but it does not take any parameters. Can anyone provide insight into wh ...

Issue with loading CSS in Angular 8 upon refreshing the page after building in production

Here is the structure of my index.html: <!doctype html> <html lang="hu"> <head> <meta charset="utf-8"> <title>WebsiteName</title> <base href="/"> <meta name="viewport& ...

Ways to include a link/href in HTML using a global constants file

I have a constants file with a links node that I need to integrate into my HTML or TypeScript file. Constants File export const GlobalConstants = { links: { classicAO: '../MicroUIs/' } } I created a public method called backToClassicAO ...