Tutorial: Building enterprise applications with Angular 6, NgRx and RxJs - Lesson 3
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
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.
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.
Thank you for your contribution.
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!