Tutorial: Building enterprise applications with Angular 6, NgRx and RxJs - Lesson 3

in #utopian-io6 years ago

NgRx Store: https://github.com/ngrx/store
Angular 6: https://github.com/angular/angular
Steem API Docs: https://developers.steem.io/

Github repository: https://github.com/mightypanda-x/ngrx-tut

I spend good part of a weekend figuring out how to make multiple asynchronous functions call and return one merged result from all those calls when they are complete. Something like this is easily achievable using forkJoin on http calls but async methods are an older generation tech which are still very much popular. Unfortunately RxJS doesn't provide us with any methods to support this out of the box.

What will you learn in this tutorial?

  • Using getContent function to get information of a post.
  • Promisifying an async method.
  • Combining promisified methods so all method returns are executed together and merged, similar to forkJoin.

Requirements

  • Complete first and second tutorial
  • Basic knowledge of JS, Angular and RxJs

Difficulty: Intermediate


Clone and run git project
Clone the git project so you can follow along with the steps and run the application

$ git clone [email protected]:mightypanda-x/ngrx-tut.git
$ cd ngrx-tut
$ npm install

Actions

profile.actions.ts

export class RetrievePostDetails implements Action {
  readonly type = ProfileActionTypes.RetrievePostDetails;
  constructor(public payload: PostMetaModel[]) {}
}

Actions are dispatched to trigger a change in state.

This action takes payload of type PostMetaModel array as input. We need author name and permlink to get post information.

export class RetrievePostDetailsSuccess implements Action {
  readonly type = ProfileActionTypes.RetrievePostDetailsSuccess;
  constructor(public payload: PostModel[]) {}
}

This action will get called when retrieving post information is successful. It takes payload of type PostModel array. This payload is then set in the state object.

export class RetrievePostDetailsFailure implements Action {
  readonly type = ProfileActionTypes.RetrievePostDetailsFailure;
  constructor(public payload: string) {}
}

This action will be called when retrieve of posts fail. It takes payload of type string which is then used log and show errors.

Effects

profile.effects.ts

@Effect()
  getPostDetails = this.actions.pipe(
    ofType(ProfileActionTypes.RetrievePostDetails),
    switchMap((action: RetrievePostDetails) => this.profileService.retrivePostsInfo(action.payload, (err, postList: PostModel[]) => {
      if (err) {
        catchError(error => this.profileService.handlePostRetrieveError(error));
      }
      if (postList.length > 0) {
        this.store.dispatch(new RetrievePostDetailsSuccess(postList));
      }
    }))
  );

Effect intercepts the RetrievePostDetails action and triggers call to service. Service then calls either the error method or the success action.

Service

profile.service.ts
All the above code was mostly basic NgRx code. This is where the actual magic happens and the reason for the tutorial.

  private getPostInformation(author, permlink): Promise<any> {
    return new Promise((resolve, reject) => {
      steem.api.getContent(author, permlink, (err, postInformation) => {
        if (err) {
          reject(new Error(err));
        } else {
          resolve(postInformation);
        }
      });
    });
  }

This method will promisify the getContent async method. We make a call using steem api getContent method and pass in a callback method. That callback method will either resolve or reject the response. Promise will then be returned by the method.

public retrivePostsInfo(bids: PostMetaModel[], cb): Array<any> {
    const methodCalls = [];
    _.map(bids, (bid) => {
      methodCalls.push(this.getPostInformation(bid.author, bid.permlink));
    });
    Promise.all(
      methodCalls
    ).then((results) => {
      cb(null, results);
    });
    return [];
  }

This method will call above method one at a time and then combine all the promises using Promise.all method. Once all the promises are resolved, then is executed for Promise.all which returns a combined result from all the calls made.

Profile Reducer

profile.reducers.ts

case ProfileActionTypes.RetrievePostDetailsSuccess: {
   return action.payload;
}

Reducer will simply update the state object with new information.

User Profile Component

user-profile.component.ts

  getPosts() {
    const inputData = [];
    inputData.push({
      author: 'mightypanda',
      permlink: 'esteem-1-6-0-cannot-exit-set-pin-screen-without-setting-any-pin'
    }, {
      author: 'mightypanda',
      permlink: 'steem-curator-sorting-feature-and-utopian-posts'
    }, {
      author: 'mightypanda',
      permlink: 'steemcurator-com-update-sorting-and-special-posts-overview'
    });
    this.store.dispatch(new ProfileActions.RetrievePostDetails(inputData));
  }
..............
this.userPosts = _.get(user, 'posts');

User Profile Component is where will dispatch action and subscribe to change in store.

user-profile.component.html

<div class="col-md-9">
    <div *ngFor="let post of userPosts" class="col-md-12 postInfo">
      <h4>{{post.title}}</h4>
      <span>Category: {{post.category}}</span><br>
      <span>Total Votes: {{post.active_votes.length}}</span>
    </div>
  </div>

This code simply iterates over the data array and displays the results on the page.

ezgif.com-video-to-gif.gif

Running the application

Go the terminal and type

$ ng serve

This will compile and run the application on http://localhost:4200. Click on Get Posts link and it will retrieve data for some posts.

GitHub for the tutorial:

https://github.com/mightypanda-x/ngrx-tut

Sort:  

Thank you for your contribution.

  • Nice work on the explanations of your code, although adding a bit more comments to the code can be helpful as well.

Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, click here.


Need help? Write a ticket on https://support.utopian.io/.
Chat with us on Discord.
[utopian-moderator]

Thanks for the review

Thank you for making this. I am trying to learn Steemconnect integration with a website at the moment and I am finding these tutorials useful. I will try to begin Lesson 1 soon and see if I can follow along. I will be supporting your useful content with my upvote.

Thanks, I appreciate it

Congratulations! This post has been upvoted from the communal account, @minnowsupport, by mightyPanda from the Minnow Support Project. It's a witness project run by aggroed, ausbitbank, teamsteem, someguy123, neoxian, followbtcnews, and netuoso. The goal is to help Steemit grow by supporting Minnows. Please find us at the Peace, Abundance, and Liberty Network (PALnet) Discord Channel. It's a completely public and open space to all members of the Steemit community who voluntarily choose to be there.

If you would like to delegate to the Minnow Support Project you can do so by clicking on the following links: 50SP, 100SP, 250SP, 500SP, 1000SP, 5000SP.
Be sure to leave at least 50SP undelegated on your account.

Hey @mightypanda
Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!

Coin Marketplace

STEEM 0.30
TRX 0.12
JST 0.032
BTC 60147.86
ETH 2985.82
USDT 1.00
SBD 3.83