以下是解决同一问题的两种方法,是对用户在文本框中输入的某些字符进行反应性搜索。第一个解决方案来自NGRX示例,第二个解决方案是来自Egghead即时搜索课程。
- 第一个解决方案使用
Observable
时,第二个解决方案使用Subject
。 -
Observable
解决方案使用takeUntil
仅调用服务器一次。Subject
解决方案使用distinctUntilChanged
。
有人可以用这两种方法解释优点和缺点吗?
使用可观察的搜索:
@Injectable()
export class BookEffects {
@Effect()
search$: Observable<Action> = this.actions$
.ofType(book.ActionTypes.SEARCH)
.debounceTime(300)
.map(toPayload)
.switchMap(query => {
if (query === '') {
return empty();
}
const nextSearch$ = this.actions$.ofType(book.ActionTypes.SEARCH).skip(1);
return this.googleBooks.searchBooks(query)
.takeUntil(nextSearch$)
.map(books => new book.SearchCompleteAction(books))
.catch(() => of(new book.SearchCompleteAction([])));
});
constructor(private actions$: Actions, private googleBooks: GoogleBooksService) { }
}
@Component({
selector: 'bc-find-book-page',
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<bc-book-search [query]="searchQuery$ | async" [searching]="loading$ | async" (search)="search($event)"></bc-book-search>
<bc-book-preview-list [books]="books$ | async"></bc-book-preview-list>
`
})
export class FindBookPageComponent {
searchQuery$: Observable<string>;
books$: Observable<Book[]>;
loading$: Observable<boolean>;
constructor(private store: Store<fromRoot.State>) {
this.searchQuery$ = store.select(fromRoot.getSearchQuery).take(1);
this.books$ = store.select(fromRoot.getSearchResults);
this.loading$ = store.select(fromRoot.getSearchLoading);
}
search(query: string) {
this.store.dispatch(new book.SearchAction(query));
}
}
使用主题搜索:
import { Component } from '@angular/core';
import { WikipediaSearchService } from './wikipedia-search.service';
import { Subject } from 'rxjs/Subject';
//application wide shared Rx operators
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/switchMap';
@Component({
moduleId: module.id,
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.css']
})
export class AppComponent {
items:Array<string>;
term$ = new Subject<string>();
constructor(private service:WikipediaSearchService) {
this.term$
.debounceTime(400)
.distinctUntilChanged()
.switchMap(term => this.service.search(term))
.subscribe(results => this.items = results);
}
}
<div>
<h2>Wikipedia Search</h2>
<input (input)="term$.next($event.target.value)">
<ul>
<li *ngFor="let item of items">{{item}}</li>
</ul>
</div>
行为主题是一种主题,一个主题是一种特殊的可观察类型,因此您可以像任何其他可观察到的消息一样订阅消息。行为主题的独特特征是:
- 行为主题需要一个初始值,因为即使尚未收到下一个() ,它也必须始终返回订阅值
- 订阅后,它返回主题的最后值。常规可观察的仅在接收到Onnext时才触发在任何时候,您都可以使用getValue()方法在不可观察的代码中检索主题的最后值。
- 与可观察到的受试者的独特特征是:
除了是可观察的外,这是一个观察者,因此除了订阅它外,还可以将值发送给对象。另外,您可以使用Asobervable()方法从行为主题中观察到可观察到的行为主题。
可观察的是一种通用,行为主体在技术上是可观察到的子类型,因为行为主体是具有特定素质的可观察到的。
可以使用主题为obsobservable()从常规主题和行为主题创建可观察到的。唯一的区别是,您无法使用Next()方法将值发送到可观察的值。
在Angular2服务中,我将使用行为主题作为数据服务作为Angular服务,通常在组件和行为主题之前初始化,可确保消耗服务的组件即使没有新的更新,也可以接收最后更新的数据对此数据。简而