See the current implementaion of code, we have a smart component, and inside the smart component we are using both 'serivce' and 'store'.

In the large application, what we really want is one service to handle the application state instead of two or more. And also we need response to the user action to get new data, all the requirements actaully can be handled by 'Store'.

import {Component, OnInit} from '@angular/core';
import {Store} from '@ngrx/store';
import {ThreadsService} from "../services/threads.service";
import {AppState} from "../store/application-state";
import {AllUserData} from "../../../shared/to/all-user-data";
import {LoadUserThreadsAction} from "../store/actions";
import {Observable} from "rxjs";
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/skip';
import {values, keys, last} from 'ramda';
import {Thread} from "../../../shared/model/thread.interface";
import {ThreadSummary} from "./model/threadSummary.interface"; @Component({
selector: 'thread-section',
templateUrl: './thread-section.component.html',
styleUrls: ['./thread-section.component.css']
})
export class ThreadSectionComponent implements OnInit { userName$: Observable<string>;
counterOfUnreadMessages$: Observable<number>;
threadSummary$: Observable<ThreadSummary[]>; constructor(private store: Store<AppState>,
private threadsService: ThreadsService) { this.userName$ = store.select(this.userNameSelector); this.counterOfUnreadMessages$ = store.select(this.unreadMessageCounterSelector); this.threadSummary$ = store.select(this.mapStateToThreadSummarySelector.bind(this))
} mapStateToThreadSummarySelector(state: AppState): ThreadSummary[] {
const threads = values<Thread>(state.storeData.threads);
return threads.map((thread) => this.mapThreadToThreadSummary(thread, state));
} mapThreadToThreadSummary(thread: Thread, state: AppState): ThreadSummary {
const names: string = keys(thread.participants)
.map(participantId => state.storeData.participants[participantId].name)
.join(', ');
const lastMessageId: number = last(thread.messageIds);
const lastMessage = state.storeData.messages[lastMessageId];
return {
id: thread.id,
participants: names,
lastMessage: lastMessage.text,
timestamp: lastMessage.timestamp
};
} userNameSelector(state: AppState): string {
const currentUserId = state.uiState.userId;
const currentParticipant = state.storeData.participants[currentUserId]; if (!currentParticipant) {
return "";
} return currentParticipant.name;
} unreadMessageCounterSelector(state: AppState): number {
const currentUserId: number = state.uiState.userId; if (!currentUserId) {
return ;
} return values<Thread>(state.storeData.threads)
.reduce(
(acc: number, thread) => acc + (thread.participants[currentUserId] || )
, );
} ngOnInit() { this.threadsService.loadUserThreads()
.subscribe((allUserData: AllUserData) => {
this.store.dispatch(new LoadUserThreadsAction(allUserData))
});
} }

So what we want to do to improve the code is to "remove the service from the component, let it handle by ngrx/effect" lib.

Here instead we call the service to get data, we will dispatch an action call 'LoadUserTreadsAction', and inside this action, will have side effect either "UserTreadsLoadSuccess" or "UserTreadsLoadError".

Create a effect service:

import {Injectable} from '@angular/core';
import {Action} from '@ngrx/store';
import {Actions, Effect} from "@ngrx/effects";
import {ThreadsService} from "../../services/threads.service";
import {LOAD_USER_THREADS_ACTION, LoadUserThreadsSuccess} from "../actions";
import {Observable} from "rxjs"; @Injectable()
export class LoadUserThreadsEffectService { constructor(private action$: Actions, private threadsService: ThreadsService) {
} @Effect()
userThreadsEffect$: Observable<Action> = this.action$
.ofType(LOAD_USER_THREADS_ACTION) // only react for LOAD_USER_THREADS_ACTION
.switchMap(() => this.threadsService.loadUserThreads()) // get data from service
.map((allUserData) => new LoadUserThreadsSuccess(allUserData)) // After get data, dispatch success action
}

And of course, we need to import the lib:

..
import {EffectsModule} from "@ngrx/effects";
import {LoadUserThreadsEffectService} from "./store/effects/load-user-threads.service"; @NgModule({
declarations: [
AppComponent
],
imports: [
..
EffectsModule.run(LoadUserThreadsEffectService),
],
providers: [
ThreadsService
],
bootstrap: [AppComponent]
})
export class AppModule {
}

We need to change reudcer, instead of add case for 'LOAD_USER_THREAD_ACTION', we should do 'LOAD_USER_THREADS_SUCCESS':

export function storeReducer(state: AppState = INITIAL_APPLICATION_STATE, action: Action): AppState {

  switch(action.type) {
case LOAD_USER_THREADS_SUCCESS:
return handleLoadUserThreadsAction(state, action);
default:
return state;
}
}

Last, in our component, we dispatch 'LoadUserThreadsAction':

  ngOnInit() {

    this.store.dispatch(new LoadUserThreadsAction())
}

Github

[Angular] NgRx/effect, why to use it?的更多相关文章

  1. [Angular] How to get Store state in ngrx Effect

    For example, what you want to do is navgiate from current item to next or previous item. In your com ...

  2. [Angular] Ngrx/effects, Action trigger another action

    @Injectable() export class LoadUserThreadsEffectService { constructor(private action$: Actions, priv ...

  3. ngRx 官方示例分析 - 6 - Effect

    @ngrx/effect 前面我们提到,在 Book 的 reducer 中,并没有 Search 这个 Action 的处理,由于它需要发出一个异步的请求,等到请求返回前端,我们需要根据返回的结果来 ...

  4. [转]VS Code 扩展 Angular 6 Snippets - TypeScript, Html, Angular Material, ngRx, RxJS & Flex Layout

    本文转自:https://marketplace.visualstudio.com/items?itemName=Mikael.Angular-BeastCode VSCode Angular Typ ...

  5. 手把手教你用ngrx管理Angular状态

    本文将与你一起探讨如何用不可变数据储存的方式进行Angular应用的状态管理 :ngrx/store——Angular的响应式Redux.本文将会完成一个小型简单的Angular应用,最终代码可以在这 ...

  6. 如何在AngularX 中 使用ngrx

    ngrx 是 Angular框架的状态容器,提供可预测化的状态管理. 1.首先创建一个可路由访问的模块 这里命名为:DemopetModule. 包括文件:demopet.html.demopet.s ...

  7. ngRx 官方示例分析 - 4.pages

    Page 中通过构造函数注入 Store,基于 Store 进行数据操作. 注意 Component 使用了 changeDetection: ChangeDetectionStrategy.OnPu ...

  8. ngRx 官方示例分析 - 3. reducers

    上一篇:ngRx 官方示例分析 - 2. Action 管理 这里我们讨论 reducer. 如果你注意的话,会看到在不同的 Action 定义文件中,导出的 Action 类型名称都是 Action ...

  9. angular版聊天室|仿微信界面IM聊天|NG2+Node聊天实例

    一.项目介绍 运用angular+angular-cli+angular-router+ngrx/store+rxjs+webpack+node+wcPop等技术实现开发的仿微信angular版聊天室 ...

随机推荐

  1. BZOJ2243: [SDOI2011]染色(树链剖分/LCT)

    Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如 ...

  2. 字符设备驱动-----Linux中断处理体系结构

    一.中断处理体系结构的初始化 Linux内核将所有的中断统一编号,使用一个irq_desc结构数组来描述这些中断;每个数组项对应一个中断,也可能是一组中断,它们共用相同的中断号,里面记录了中断的名称. ...

  3. git还原文件

    http://jingyan.baidu.com/album/e4511cf33479812b855eaf67.html

  4. Centos下Elasticsearch安装详细教程

    Centos下Elasticsearch安装详细教程 1.Elasticsearch简介 ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于 ...

  5. 彩票案例-frame,center和bounds属性

    控件的属性: 二.frame.center和bounds属性 " 在iOS中,每一个控件都是继承于UIView的.都会有视图的属性存在,控制这个视图的位置就有Frame和Bounds两个属性 ...

  6. LeetCode Algorithm 05_Longest Palindromic Substring

    Given a string S, find the longest palindromic substring in S. You may assume that the maximum lengt ...

  7. 关于DOM的有关总结

    1.获取DOM元素 document.getElementById()  通过id获取DOM元素 document.getElementsByClassName() 通过类名获取DOM元素 docum ...

  8. 最新GitHub新手使用教程(Linux/Ubuntu Git从安装到使用)——详细图解

    说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 一.叙述 1.说明:需要在Windows 安装Git的同学,可以查看该篇博客 https://blog.csdn.net/qq_4 ...

  9. 使用BeautifulSoup爬取“0daydown”站点的信息(2)——字符编码问题解决

    上篇中的程序实现了抓取0daydown最新的10页信息.输出是直接输出到控制台里面.再次改进代码时我准备把它们写入到一个TXT文档中.这是问题就出来了. 最初我的代码例如以下: #-*- coding ...

  10. php模拟顺序栈基本操作

    php模拟顺序栈基本操作 一.总结 写函数什么永远记住边界情况:比如 echo "栈已满!<br/>" ;  栈已空这种,那就能多考虑几种情况,代码就很正宗了 1.对象 ...