[Angular 2] Handle Reactive Async opreations in Service

When you use ngrx/store and you want to fire a service request. When it sucessfully return the response, you need to dispatch action to tell the store update.

So one pattern can be considered to follow is:

import {Http, Headers} from ‘@angular/http‘;
import {Injectable} from ‘@angular/core‘;
import {Store} from ‘@ngrx/store‘;
import {Observable} from "rxjs/Observable";
import ‘rxjs/add/operator/map‘;

import {AppStore} from ‘../models/appstore.model‘;
import {Item} from ‘../models/item.model‘;

const BASE_URL = ‘http://localhost:3000/items/‘;
const HEADER = { headers: new Headers({ ‘Content-Type‘: ‘application/json‘ }) };

@Injectable()
export class ItemsService {
  items: Observable<Array<Item>>;

  constructor(private http: Http, private store: Store<AppStore>) {
    this.items = store.select(‘items‘);
  }

  loadItems() {
    this.http.get(BASE_URL)
      .map(res => res.json())
      .map(payload => ({ type: ‘ADD_ITEMS‘, payload }))
      .subscribe(action => this.store.dispatch(action));
  }

  saveItem(item: Item) {
    return (item.id) ? this.updateItem(item) : this.createItem(item);
  }

  createItem(item: Item) {
     return this.http.post(`${BASE_URL}`, JSON.stringify(item), HEADER)
      .map(res => res.json())
      .do(payload => {
        const action = { type: ‘CREATE_ITEM‘, payload };
        this.store.dispatch(action)
      });
  }

  updateItem(item: Item) {
    return this.http.put(`${BASE_URL}${item.id}`, JSON.stringify(item), HEADER)
      .do(action => this.store.dispatch({ type: ‘UPDATE_ITEM‘, payload: item }));
  }

  deleteItem(item: Item) {
    return this.http.delete(`${BASE_URL}${item.id}`)
      .do(action => this.store.dispatch({ type: ‘DELETE_ITEM‘, payload: item }));
  }
}

In this ItemService, we get Items from store:

  items: Observable<Array<Item>>;

  constructor(private http: Http, private store: Store<AppStore>) {
    this.items = store.select(‘items‘);
  }

To change state, it flows the style that

  • Call the backend
  • if success generate action
  • dispatch the action
 createItem(item: Item) {
     return this.http.post(`${BASE_URL}`, JSON.stringify(item), HEADER)
      .map(res => res.json())
      .do(payload => {
        const action = { type: ‘CREATE_ITEM‘, payload };
        this.store.dispatch(action)
      });
  }

In the controller:

  saveItem(item: Item) {
    this.itemsService.saveItem(item)
      .subscribe( (res) => {this.resetItem()},
                  (err) => {console.error(err)},
                 () => {console.info("Completed")});

If you notice, in loadItems, I didn‘t‘ use do() to dispatch action and subscribe in controller, instead I subscribe in service, this is because in controller, it doesn‘t expect receive anything from service:

  constructor(private itemsService: ItemsService,
              private gadgetService: GadgetService,
              private store: Store<AppStore>) {
    this.items = itemsService.items;
    itemsService.loadItems();
  }

We base on async pipe to update the dom:

      <items-list [items]="items | async"
        (selected)="selectItem($event)" (deleted)="deleteItem($event)">
      </items-list>

But for createItem, deleteItem, we use do() to dispatch action and subscribe action, this is because we want to confrim weather it successfully updated, then we want to clear the input fields.

时间: 06-22

[Angular 2] Handle Reactive Async opreations in Service的相关文章

[Angular] Bind async requests in your Angular template with the async pipe and the &quot;as&quot; keyword

Angular allows us to conveniently use the async pipe to automatically register to RxJS observables and render the result into the template once the request succeeds. This has some drawbacks, especially if we want to bind the same data in multiple par

angular中的路由,watch,service和ajax

一.$watch. 先说说angular的watch它可以监视数据模型的变化,$scope.$watch('name',function(new,old){});watch 有两个参数,第一个是监视的名字,第二个是当被监视者发生变化时,就执行的一个函数.这个函数里面也有两个参数,第一个是新值,第二个是上一个的值.注意这个上一个的值是相对于新值而言的.当被监视者是一个方法时,它将返回方法的返回值. 二.创建服务service 先说说服务的作用,它相当于抽取公共的方法.再来说说如何创建服务.先要明白

[Angular Directive] Create a Template Storage Service in Angular 2

You need to define a <template> to be able to use it elsewhere in your app as a TemplateRef. You can store these TemplateRefs in a Service and then access them from any @Directive or @Component in your app. We want to create a service and a componen

[Angular Directive] Build a Directive that Tracks User Events in a Service in Angular 2

A @Directive is used to add behavior to elements and components in your application. This makes @Directives ideal for behaviors such as "tracking" which don't belong in a Component, but do belong as a behavior in your application. import {Direct

angular 服务 service factory provider constant value

angular服务 服务是对公共代码的抽象,由于依赖注入的要求,服务都是单例的,这样我们才能到处注入它们,而不用去管理它们的生命周期. angular的服务有以下几种类型: 常量(Constant): 用于声明不会被修改的值. 变量(Value): 用于声明会被修改的值. 服务(Service): 这个名称跟服务这个大概念同名,就种行为就像是给自己孩子取名为"孩子".只需要创建这个服务,然后等angular把它new出来,保存这个服务,然后就可以到处注入了. 工厂(Factory): 

[Angular] Design API for show / hide components based on Auth

Simple Auth service: import { Injectable } from '@angular/core'; import {HttpClient} from '@angular/common/http'; import {Observable} from 'rxjs/Observable'; import {User} from '../model/user'; import {BehaviorSubject} from 'rxjs/BehaviorSubject'; im

[Angular] USING ZONES IN ANGULAR FOR BETTER PERFORMANCE

Link to the artical. Zone detects any async opreations. Once an async oprations happens in Angular, Zone will notify change detection to kick in. Images we have 5000 svg box displaying on the screen. And each svg elements and three event listener on

Angular 2 + 折腾记 :(7) 初步了解表单:模板驱动及数据驱动及脱坑要点

前言 表单在整个系统中的作用相当重要,这里主要扯下响应表单的实现方式. 首先需要操作表单的模块引入这两个模块: import { FormsModule, ReactiveFormsModule } from '@angular/forms'; 表单控件响应的几种状态 模板驱动表单依赖FormsModule,数据驱动的表单依赖FormsModule,ReactiveFormsModule 一般做表单校验及操作推荐用数据驱动的方式,好维护和理解.. 模板驱动 模板驱动:主要是依赖[(ngModel

[Angular2 Router] Load Data Based on Angular 2 Route Params

You can load resource based on the url using the a combination of ActivatedRouteand Angular 2’s Http service. Since the params and Http are both streams, you can use RxJS to get the data off the param then switchMap over to an Http request using that