繁体   English   中英

Angular 2-永远不会被http.get调用

[英]Angular 2 - http.get never being call

我正在学习Angular 4,遇到了一个我似乎找不到解决方案的问题。 这里是上下文:我有一个简单的应用程序,显示有关美国总统的信息。 后端是webapi提供的rest API ...效果很好。 前端是一个Angular应用程序。

我将问题简化为3个组件,1个数据服务和1个模型。 这是模型:

export class President {
  constructor(
    public id: number,
    public presidentName: string,
    public presidentNumber: number,
    public yearsServed: string,
    public partyAffiliation: string,
    public spouse: string) {}
}

这三个组件是1. SearchComponent 2. HomeComponent 3. PresidentComponent

当应用程序启动时,它将加载ApplicationComponent-它是根组件:

import { Component, ViewEncapsulation } from '@angular/core';

@Component({
    selector: 'my-app',
    template: `
        <search-component></search-component>
        <home-component></home-component>
    `
})
export class ApplicationComponent  {}

PresidentComponent是HomeComponent的子组件。 加载home组件时,它将对api进行http调用以获取总裁列表,并为返回的每一行呈现1 PresidentComponent。 这很好。

我想做的是实现一个搜索功能,其中dataService公开一个EventEmitter并提供搜索方法,如下所示:

import { Injectable, EventEmitter, Output } from '@angular/core'
import { President } from '../models/President'

import { Http } from '@angular/http';
import 'rxjs/add/operator/toPromise';
import 'rxjs/add/operator/map';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class DataService {

    constructor(private http: Http) {
    }

    searchEvent: EventEmitter<any> = new EventEmitter();

    // simple property for the url to the api
    get presidentUrl {
        return "http://localhost:51330/api/presidents";
    }

    search(params: any): Observable<President[]> {
        let encParams = encodeParams(params);
        console.log(encParams);
        return this.http
          .get(this.presidentUrl, {search: encParams})
          .map(response => response.json());
    }


    getParties(): String[] {
        return ['Republican', 'Democrat', 'Federalist', 'Whig', 'Democratic-Republican', 'None'];
    }

    getPresidents(): Observable<President[]> {
        return this.http.get(this.presidentUrl)
                        .map(response => response.json());
    }

}

/**
 * Encodes the object into a valid query string.
 * this function is from the book Angular2 Development with TypeScript
 */
function encodeParams(params: any): URLSearchParams {
    return Object.keys(params)
      .filter(key => params[key])
      .reduce((accum: URLSearchParams, key: string) => {
        accum.append(key, params[key]);
        return accum;
      }, new URLSearchParams());
  }

搜索组件包含搜索表单,当单击搜索按钮时,它将执行onSearch()函数并在数据服务上发出调用:

onSearch(){
            if(this.formModel.valid){
                console.log('emitting event from search.ts');
                this.dataService.searchEvent.emit(this.formModel.value);
            }
        }

然后,在HomeComponent中,我想订阅此事件,并在触发时通过dataservice执行搜索:

 ngOnInit(): void {
        //when component loads, get list of presidents
        this.dataService.getPresidents()
        .subscribe(
            presidents => {
                console.log('sub');
                this.presidents = presidents;

            },
            error => console.error(error)
        )

    //when search event is fired, do a search
    this.dataService.searchEvent
        .subscribe(
            params => {
                console.log('in home.ts subscribe ' + JSON.stringify(params));
                this.result = this.dataService.search(params);
            },
            err => console.log("cant get presidents. error code: %s, URL: %s"),
            () => console.log('done')
        );
    }

当我在浏览器中运行此命令时,除http调用外,其他所有功能都不会执行。 如果我对dataservice本身中的http.get调用执行subscription(),它将执行,但是为什么要在HomeComponent上设置订阅时为什么要这样做呢? 我想在HomeComponent中处理Observable,并根据搜索结果更新UI中显示的行长列表。 任何意见是极大的赞赏。

在服务中使用EventEmitter的整个想法是不正确的。 EventEmitter应该与@Output属性一起使用,以将数据从子组件发送到其父组件。

即使EventEmitter是Subject的子类,您也不应该在服务中使用它。 因此,将服务注入您的组件,订阅其​​在组件中的可观察对象,并在需要时使用EventEmitter向父组件发出事件。

在代码中this.result = this.dataService.search(params); ,结果是可观察的。 您尚未订阅。

在这种情况下,您应该使用async管道来显示数据。

为什么不使用rxjs Subject 这是我的建议:

数据服务:

import { Observable, Subject } from "rxjs";
import 'rxjs/add/operator/catch';

@Injectable()
export class DataService {
  private _dataSubject = new Subject();

  constructor(private http: Http) {
      this.http.get(this.presidentUrl)
         .map(response => this._dataSubject.next(response.json()))
         .catch(err => this._dataSubject.error(err));        
       );
     }

// simple property for the url to the api
get presidentUrl {
    return "http://localhost:51330/api/presidents";
}

search(params: any){
    let encParams = encodeParams(params);
    console.log(encParams);
    this.http
      .get(this.presidentUrl, {search: encParams})
      .map(response => this._dataSubject.next(response.json()))
      .catch(err => this._dataSubject.error(err));
}


getParties(): String[] {
    return ['Republican', 'Democrat', 'Federalist', 'Whig', 'Democratic-Republican', 'None'];
}

getPresidents(): Observable<President[]> {
    return this._dataSubject;
}

SearchComponent:

 onSearch(){
         if(this.formModel.valid){
            console.log('emitting event from search.ts');
            this.dataService.search(this.formModel.value);
        }
    }

通过这些修改,您应该只能在homeCompoent中只有1个订阅者,然后每次调用onSearch()onSearch()获取发出的新数据。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM