Combining actions in a chain within an NgRx effect for Angular

After successfully working on an effect, I now face the challenge of chaining it with a service called in a subsequent action after updating the state in the initial action through a reducer.

Here is the effect code:

@Effect()
uploadSpecChange$: Observable<Action> = this.actions$.pipe(
    ofType(AppActions.WorkspaceActionTypes.UploadChange),
    switchMap((x: any) => {
        let f = new FileReader();
        f.readAsText(x.payload);
        return fromEvent(f, 'load');
    }),
    map((result: any) => {
        const raw = (<FileReader>result.target).result as string;
        const res = JSON.parse(raw);
        // console.log(res);
        return
            new AppActions.UploadComplete(res),
            new AppActions.PerformCalc()
    })
);

I included the second action but am currently encountering an error related to Observables.

Answer №1

If you wish to trigger multiple actions from an effect, you can return an array of actions and change your map to a mergeMap:

@Effect()
uploadSpecChange$: Observable<Action> = this.actions$.pipe(
    ofType(AppActions.WorkspaceActionTypes.UploadChange),
    switchMap((x: any) => {
        let f = new FileReader();
        f.readAsText(x.payload);
        return fromEvent(f, 'load');
    }),
    mergeMap((result: any) => {
        const raw = (<FileReader>result.target).result as string;
        const res = JSON.parse(raw);
        // console.log(res);
        return [
            new AppActions.UploadComplete(res),
            new AppActions.PerformCalc()
        ];
    })
);

However, if you want the PerformCalc action to be dispatched after the UploadComplete action is completed, you should make PerformCalc a side effect of UploadComplete:

@Effect()
uploadSpecChange$: Observable<Action> = this.actions$.pipe(
    ofType(AppActions.WorkspaceActionTypes.UploadChange),
    switchMap((x: any) => {
        let f = new FileReader();
        f.readAsText(x.payload);
        return fromEvent(f, 'load');
    }),
    map((result: any) => {
        const raw = (<FileReader>result.target).result as string;
        const res = JSON.parse(raw);
        // console.log(res);
        return new AppActions.UploadComplete(res);
    })
);

@Effect()
uploadComplete$: Observable<Action> = this.actions$.pipe(
    ofType(AppActions.WorkspaceActionTypes.UploadComplete),
    map(() => new AppActions.PerformCalc())
);

Answer №2

When dealing with multiple actions being returned in an @Effect,

it is important to utilize concatMap instead of map.

concatMap((result: any) => {
    const rawData = (<FileReader>result.target).result as string;
    const parsedData = JSON.parse(rawData);
    return [
        new AppActions.UploadComplete(parsedData),
        new AppActions.PerformCalculation()
    ]
})

Answer №3

To achieve this functionality, you can utilize the switchMap and of operators as shown below:

@Effect()
dispatchMultiActions$: Observable<Action> = this.actions$.pipe(
    ofType<SomeAction.Dispatch>(someActions.Dispatch),
    switchMap(_ =>
        of(
            new someActions.InitializeData(),
            new someActions.FetchData(),
            new someActions.DisplayData()
        )
    )
);

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

Is the && operator being utilized as a conditional statement?

While following a tutorial, I came across this code snippet that uses the 'and' operator in an unusual way. Is this related to React? Can someone provide an explanation or share documentation that clarifies it? {basket?.length > 0 && ...

What is the method for specifying a specific sub-dependency version in a package in Node.js?

Let me simplify my issue for you. I am facing troubles while trying to install two plugins, plugin A version 2.0 and plugin B version 3.0. It turns out that plugin B has plugin A as a sub-dependency with a conflicting version, resulting in a build phase e ...

What is the process for invoking a page using a JavaScript function?

My index.php has a javascript code that calls a page in the following way: id = 5; var url = 'pages/pg/'+id+'/'; f.action = urlss.toLowerCase(); return true; The issue arises when I try to call the same page with a different ID, it do ...

Is there a way to manually stop a file upload (stream) using a XMLHttpRequest on the server?

Utilizing XMLHttpRequest (Level 2) to transfer a file to a node.js server, I am currently examining the file-stream for valid headers on the server side. The goal now is to halt the upload if any errors are encountered during streaming. My XMLHttpRequest c ...

Can VueJS 1 and 2 be integrated within the same package.json configuration?

At the moment, my JavaScript files are using VueJS 1. However, I am preparing to work on a new section of the system and want to switch to VueJS 2. ...

Utilizing the $scope variable within an event in the Google Maps API

I am having an issue using $scope within this function. Where should I define the argument $scope so that it works properly? Thank you Below is the basic structure of my code with key lines included: myApp.controller('myCtrl', ['$scope&ap ...

Determine the gravitational force of a planet on falling objects and display the result in an input field

I have developed a form code that includes several dropdown menus with different options, as well as an alert popup message to prevent users from selecting the same planet more than once. Additionally, I have disabled one input in a textbox because only on ...

Numerous pop-up windows displaying a variety of distinct content in each one

While working on a website, I came across a helpful jQuery pop-up function that I found on Stack Overflow. The original post can be found here. I am trying to customize each pop-up box so they contain different content from the .pop1 and .pop2 divs (parag ...

Guide to changing the color of SVG images on a live webpage

I'm having trouble changing the color of a specific part within an svg image (created in Inkscape). I believe CSS is the solution, but I can't seem to select the id from the particular SVG file. The object in the SVG has the id='ToChange&apo ...

Switching positions in Azure DevOps (Angular + API): How can the Angular configuration be modified for the designated slot?

Setting up the Angular app can be quite tricky. In our Azure Yaml pipeline publishing job, we tackle the challenge by executing a "token" replacement to tailor the configuration for the specific target environment within a tokenized artifact. Subsequently ...

`Bootstrap 4 fails to center elements vertically`

Struggling to center a panel using Bootstrap 4? Despite adding classes like align-items-center and h-100, the header continues to stay at the top of the page. Does anyone know the solution? This is in an Angular 4 project with Bootstrap. <div class=&ap ...

Experience the advanced NgPrime p-dropdown template with templating, filtering, and a clear icon that collapses when wrapped within a form element

Check out this link for a demo Whenever I enclose the code below in a </form> element, the drop-down menu collapses. <h5>Advanced with Templating, Filtering and Clear Icon</h5> <p-dropdown [options]="countries" [(ngModel)]=& ...

Can the browser doc mode be switched frequently?

My web application is built using AngularJS, but we also have a legacy web app that functions only in quirks mode and is included via an iframe on one of our pages. The challenge is to make this legacy app work within our main browser-based application, wh ...

What causes parameters to be undefined when making a DELETE request in my Next.js application running on version 14.1.4?

I am encountering an issue with my DELETE mapping export async function DELETE({params} : {params: {id: string}}) { try { const loanToDelete = await prisma.loan.findUnique({ where: { id: parseInt(params.id) } }) if (!loanToDelete ...

Record the cumulative amount computed using an asynchronous callback

If I use code similar to the one below, I am able to obtain the total byte size value every time a file is added. How can I log out only the total files size after it has been calculated in the fs.stat callback? var fs = require('fs'); var to ...

Switch up the AJAX jQuery URL based on checkboxes selected

As I work with four checkboxes and fetch JSON data from an API using jQuery AJAX, my goal is to dynamically change the URL based on checkbox selection. Although the ajax code functions properly within the click function, it fails when placed outside of it. ...

Check out the new Bootstrap 5 form when it's successfully validated

I need to execute some JavaScript if my form is valid. I am using Bootstrap 5 and found this code, but I am unsure how to add 'if form.is_valid {}' <script> (function () { 'use strict' const forms = document.querySelectorAll(&apos ...

Tips for overcoming indentation issues using ESLint?

Ever since I started using Vue 3 with ESlint, I've been encountering a new problem. Whenever I try to run my code, I am bombarded with numerous errors like: --fix option.</p> I'm looking for ways to disable this troublesome feature of ESl ...

How can I use querySelector in JavaScript to target all div elements that have the same class?

I'm having an issue with the document.querySelector in my JavaScript code. It currently only selects the first div that contains the class "test", but I need it to select all such divs. Is there a way to achieve this using my existing JavaScript? ...

Error encountered following the import from a newly created directory in Angular 2

Recently, I've been working on adding a new folder within my application. Let's assume that I already have components A and B set up. I decided to create a new folder called app/test. Inside this folder, I created a file named test-component.ts ...