如何从字符串输入中使用 RxJs 5 的主题和去抖动
How to use subject and debounce with RxJs 5 from a string input
我不明白 Subject 对象如何为我试图在 Angular2 中实现的 Suggestion/Search 服务 工作。
假设每次输入更改时都会调用 generateSuggestions 以用于自动完成。
我不明白为什么我无法从 "next()" 调用中得到一些东西,typescript 编译器说它返回一个 void 类型。
我的目标是将每个更改提交到一个对象,该对象将决定每 500 毫秒在服务器上调用一个函数,而不是在每个键输入时发送垃圾邮件。
import { Jsonp, Response, Http } from 'angular2/http';
import * as Rx from 'rxjs/Rx';
import { Injectable } from 'angular2/core';
@Injectable()
export class SearchService {
queryStream = new Rx.Subject();
constructor(public http: Http) {
}
generateSuggestions(query: string) {
this.queryStream
.next(query)
.debounce(500) // Compiler error: Debounce does not exist on type "void"
.map(
query => this.http.get('hellow')
.map( (res: Response) => res.json() )
.subscribe( results => console.log(results) )
);
}
}
我可以简单地做到这一点 JS/Typescript 但我真的很想尝试使用 RxJs,因为它已经被 Angular2 使用了。
这里犯了哪些错误?他们的官方网站上没有任何示例,文档真的很差。
注意:如果你有更好的选择,就post另一个答案,我会选择它作为答案。
我的结果表明我没有很好地理解 Rx.Subject 的目的。
使用 ngModel 和 ngModelChange 的建议解决方案
因为我目前只在我的组件中使用 ngModel,所以我不得不将 [(ngModel)] 拆分为 [ngModel] 和 (ngModelChange)
在组件构造函数中
使用 Rx.Subject(理论上它与 EventEmitter 相同,但也许它已经改变,因为我们无法再使用它访问所有 Rx.Subject 方法)参数化去抖并调用服务来检索值。
每次击键:
输入 -> (ngModelChange) -> eventEmitterComponentInstance.next(InputValue)
代码
SuggestMultipleStringComponent.ts
@Component({
template: `<input [ngModel]="userInput"
(ngModelChange)="userInputChanged($event)" />`
providers: [SearchService]
})
export class SuggestMultipleStringComponent {
private typeAheadEventEmitter = new Rx.Subject<string>();
private userInput: string;
constructor(private _searchService: SearchService) {
this.typeAheadEventEmitter
.pipe(
debounceTime(700),
switchMap(val => {
console.log('called once')
return this._searchService.callSomething();
})
).subscribe(results => {
console.log(results);
}, error => {
console.log('error logged:');
console.log(error);
});
}
userInputChanged(value: string) {
this.userInput = value;
this.typeAheadEventEmitter.next(value);
}
}
SearchService.ts
@Injectable()
export class SearchService {
constructor(private http: Http) {
this.http = http;
}
callSomething() {
return this.http.get('some/url')
.map((res: Response) => res.json());
}
}
我不明白 Subject 对象如何为我试图在 Angular2 中实现的 Suggestion/Search 服务 工作。
假设每次输入更改时都会调用 generateSuggestions 以用于自动完成。
我不明白为什么我无法从 "next()" 调用中得到一些东西,typescript 编译器说它返回一个 void 类型。
我的目标是将每个更改提交到一个对象,该对象将决定每 500 毫秒在服务器上调用一个函数,而不是在每个键输入时发送垃圾邮件。
import { Jsonp, Response, Http } from 'angular2/http';
import * as Rx from 'rxjs/Rx';
import { Injectable } from 'angular2/core';
@Injectable()
export class SearchService {
queryStream = new Rx.Subject();
constructor(public http: Http) {
}
generateSuggestions(query: string) {
this.queryStream
.next(query)
.debounce(500) // Compiler error: Debounce does not exist on type "void"
.map(
query => this.http.get('hellow')
.map( (res: Response) => res.json() )
.subscribe( results => console.log(results) )
);
}
}
我可以简单地做到这一点 JS/Typescript 但我真的很想尝试使用 RxJs,因为它已经被 Angular2 使用了。
这里犯了哪些错误?他们的官方网站上没有任何示例,文档真的很差。
注意:如果你有更好的选择,就post另一个答案,我会选择它作为答案。
我的结果表明我没有很好地理解 Rx.Subject 的目的。
使用 ngModel 和 ngModelChange 的建议解决方案
因为我目前只在我的组件中使用 ngModel,所以我不得不将 [(ngModel)] 拆分为 [ngModel] 和 (ngModelChange)
在组件构造函数中
使用 Rx.Subject(理论上它与 EventEmitter 相同,但也许它已经改变,因为我们无法再使用它访问所有 Rx.Subject 方法)参数化去抖并调用服务来检索值。
每次击键:
输入 -> (ngModelChange) -> eventEmitterComponentInstance.next(InputValue)
代码
SuggestMultipleStringComponent.ts
@Component({
template: `<input [ngModel]="userInput"
(ngModelChange)="userInputChanged($event)" />`
providers: [SearchService]
})
export class SuggestMultipleStringComponent {
private typeAheadEventEmitter = new Rx.Subject<string>();
private userInput: string;
constructor(private _searchService: SearchService) {
this.typeAheadEventEmitter
.pipe(
debounceTime(700),
switchMap(val => {
console.log('called once')
return this._searchService.callSomething();
})
).subscribe(results => {
console.log(results);
}, error => {
console.log('error logged:');
console.log(error);
});
}
userInputChanged(value: string) {
this.userInput = value;
this.typeAheadEventEmitter.next(value);
}
}
SearchService.ts
@Injectable()
export class SearchService {
constructor(private http: Http) {
this.http = http;
}
callSomething() {
return this.http.get('some/url')
.map((res: Response) => res.json());
}
}