为什么在这个 angular2 组件中调用了两次服务?

Why is the service called twice in this angular 2 component?

我这里有组件代码,当我订阅 observable 时,服务被调用两次,但是如果我订阅 Behaviorsubject,它只会被触发一次,

我可以在我的日志中看到这些是结果,请查看下面我的组件代码 在 ngOninit 上调用了 subscribeToMap() 方法。

import { Component, OnInit } from '@angular/core';
import { Router }            from '@angular/router';

import { Observable }        from 'rxjs/Observable';
import { Subject }           from 'rxjs/Subject';

// Observable class extensions
import 'rxjs/add/observable/of';

// Observable operators
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';

import { HeroSearchService } from './hero-search-service';
import { Hero } from './../hero';

@Component({
  selector: 'hero-search',
  templateUrl: './hero-search.component.html',
  styleUrls: [ './hero-search.component.css' ],
  providers: [HeroSearchService]
})
export class HeroSearchComponent implements OnInit {
  heroes: Observable<Hero[]>;
  private searchTerms = new Subject<string>();

  constructor(
    private heroSearchService: HeroSearchService,
    private router: Router) {}

  // Push a search term into the observable stream.
  search(term: string): void {
    this.searchTerms.next(term);
    console.log("new " + term);
  }



  ngOnInit(): void {
    this.heroes = this.searchTerms
      .debounceTime(300)        // wait 300ms after each keystroke before considering the term
      .distinctUntilChanged()   // ignore if next search term is same as previous
      .switchMap(term => {
        return term   // switch to new observable each time the term changes
        // return the http search observable
        ? this.heroSearchService.search(term)
        // or the observable of empty heroes if there was no search term
        : Observable.of<Hero[]>([])})
      .catch(error => {
        // TODO: add real error handling
        console.log(error);
        return Observable.of<Hero[]>([]);
      });
      this.subscribeToMap();
  }

  subscribeToMap(): void{
     this.heroes.subscribe(() => console.log("called twice"));
     this.searchTerms.subscribe(() => console.log("called once"));
  }


  gotoDetail(hero: Hero): void {
    let link = ['/detail', hero.id];
    this.router.navigate(link);
  }
}

这是我的服务代码

import { Injectable } from '@angular/core';
import { Http }       from '@angular/http';

import { Observable }     from 'rxjs/Observable';
import 'rxjs/add/operator/map';

import { Hero }           from './../hero';

@Injectable()
export class HeroSearchService {

  constructor(private http: Http) {}

  search(term: string): Observable<Hero[]> {
    console.log("service is called");
    return this.http
               .get(`api/heroes/?name=${term}`)
               .map(response => response.json().data as Hero[]);
  }
}

非常感谢!!!

尝试替换此行:

this.heroes = this.searchTerms

有了这个:

this.heroes = this.searchTerms.asObservable()

以确保 heroes 是可观察的,并且您的代码不会意外调用 next()

您的代码将 hero 转换为 Subject,因此您仍然可以对其执行 next()。

如果正确实现订阅,它与 "unsubscribe" 方法、Observable 等无关。此行为是 Angular 本身设计的。

https://www.reddit.com/r/Angular2/comments/59532r/function_being_called_multiple_times/d95vjlz/

If you're running in development mode, it will run the function at least twice. since in development mode it does a check, changes, then rechecks to verify, where production mode only does the first check, assuming you've done your quality assurance and resolved any values the get changed post checking.

P.S。这可能是您在开发模式下将面临的下一个问题:)