在Angular版本6之前,我有一个这样编写的搜索函数:
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Observable, Subject } from 'rxjs/Rx';
import { Product } from '../products/product';
import { ProductService } from '../products/product.service';
import { Subscription } from 'rxjs';
import { SearchService } from '../services/search-service';
import { Router } from '@angular/router';
import { PagedList } from '../shared/paged-list.interface';
@Component({
selector: 'fb-product-list',
templateUrl: './product-list.component.html'
})
export class ProductListComponent implements OnInit, OnDestroy {
total$: Observable<number>;
items$: Observable<Product[]>;
product: Product;
subTimer: Subscription;
term: string = "";
currentPage: number = 1;
private pageStream = new Subject<number>();
public pluralizeMapProduct: any = {
'=0': 'No products',
'=1': '1 product',
'other': '# products'
}
constructor(
private _searchService: SearchService,
private _productService: ProductService,
private _router: Router) {
}
ngOnInit() {
this.setupSearching();
}
setupSearching(){
const searchSource = this._searchService.searchTermStream
.map(searchTerm => {
this.term = searchTerm;
return {search: searchTerm, page: 1}
});
const pageSource = this.pageStream.map(pageNumber => {
this.currentPage = pageNumber;
return {search: this.term, page: pageNumber}
});
const source:Observable<PagedList<any>> = pageSource
.merge(searchSource)
.startWith({search: this.term, page: this.currentPage})
.switchMap((params: {search: string, page: number}) => {
return this._productService.getProductsPaged(params.search, params.page, null, null)
})
.share();
this.total$ = source.pluck('meta').pluck('total_count') as Observable<number>;
this.items$ = source.pluck('data') as Observable<Product[]>;
}
goToPage(page: number, reload: boolean) {
this.pageStream.next(page);
}
}
现按照本指南重新编写:
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription, Observable, Subject, merge } from 'rxjs';
import { map, startWith, switchMap, share, pluck } from 'rxjs/operators';
import { Product } from '../products/product';
import { ProductService } from '../products/product.service';
import { SearchService } from '../services/search-service';
import { Router } from '@angular/router';
import { PagedList } from '../shared/paged-list.interface';
import { SearchSpec } from '../shared/search-spec.interface';
@Component({
selector: 'fb-product-list',
templateUrl: './product-list.component.html'
})
export class ProductListComponent implements OnInit, OnDestroy {
total$: Observable<number>;
items$: Observable<Product[]>;
product: Product;
subTimer: Subscription;
term: string = "";
currentPage: number = 1;
private pageStream = new Subject<number>();
public pluralizeMapProduct: any = {
'=0': 'No products',
'=1': '1 product',
'other': '# products'
}
constructor(
private _searchService: SearchService,
private _productService: ProductService,
private _router: Router) {
}
ngOnInit() {
this.setupSearching();
}
setupSearching(){
const searchSource = this._searchService.searchTermStream
.pipe(
map(searchTerm => {
this.term = searchTerm;
return {term: searchTerm, page: 1} as SearchSpec
})
);
const pageSource = this.pageStream
.pipe(
map(pageNumber => {
this.currentPage = pageNumber;
return {term: this.term, page: pageNumber} as SearchSpec
})
);
const source:Observable<PagedList<any>> = pageSource
.pipe(
merge(searchSource),
startWith({term: this.term, page: this.currentPage}),
switchMap((params: {term: string, page: number}) => {
return this._productService.getProductsPaged(params.term, params.page, null, null)
}),
share()
);
this.total$ = source.pipe(pluck('meta'), pluck('total_count')) as Observable<number>;
this.items$ = source.pipe(pluck('data')) as Observable<Product[]>;
}
goToPage(page: number, reload: boolean) {
this.pageStream.next(page);
}
}
VSCode在管道内部的第3个常量中抱怨这条管线:
merge(searchSource),
“Observable”类型的参数不可赋值给
“OperatorFunction”类型的参数。
类型“Observable”与签名不匹配
'(来源:Observable):Observable<{}>'
编辑
这是搜索服务(对于v6):
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
@Injectable()
export class SearchService {
searchTermStream = new Subject<string>();
sendSearchTerm(term: string) {
this.searchTermStream.next(term)
}
}
这是我为强制键入而添加的新接口SearchSpec:
export interface SearchSpec {
term: string,
page: number
}