使用 rjxs 而不是 setTimeout 函数订阅的更优雅的方式?
More elegant way to subscribe with rjxs instead of setTimeout function?
我有一个 update()
方法,我用它在 table 和 update/filter 中搜索某些条目,用于输入字段中的每个击键。
我的目标是在每次击键后等待大约 400 毫秒,然后再将请求发送到后端,以避免出现太多无意义的请求。
目前我已经用 setTimeout()
函数实现了它,但我相信 RxJS 有更优雅的方法。
update(searchInput: string) {
setTimeout(() => {
this.myService.search(searchInput)
.subscribe((res) => {
this.myArray.content = res;
});
}, 400);
}
有人知道吗?
我在代码中留下了一些评论:
const search = fromEvent(searchInput, 'input').pipe(
debounceTime(1000), // Time in milliseconds between key events
distinctUntilChanged(), // If previous query is different from current
map(event => event.target.value) // get value,
filter(query => query) // if character length greater then 0,
tap(query => console.log(`About to make an API call with query: ${query}`)),
switchMap(getCars) // Your api call
);
search.subscribe(successCallback);
您可以执行以下操作:
在HTML中:
<input type="text" #myId="ngModel" [(ngModel)]="data" />
在你的组件中:
import {
debounceTime,
distinctUntilChanged
} from "rxjs/operators";
@ViewChild('myId', {static: true}) myControl: NgModel;
ngOnInit() {
this.myControl
.valueChanges // For each changes
.pipe(
debounceTime(400),
distinctUntilChanged()
)
.subscribe(() => ...)
}
尝试使用debounce()
和distinctUntileChanged()
:
handleFilterEvent = new Subject<any>();
ngOnInit(){
this.handleFilterEvent
.debounceTime(500)
.distinctUntilChanged()
.subscribe(value => {
this.myService.search(searchInput)
.subscribe((res) => {
this.myArray.content = res;
});
});
}
onSearchChange(value){
if(value) {
this.handleFilterEvent.next(value);
}
}
HTML:
<input type="text" class="form-control"
(input)="onSearchChange($event.target.value)">
您可以使用 fromEvent
和 Viewchild
来实现
只需引用 ViewChild 如下:
@ViewChild('yourInput') inputName: any;
那么你可以简单地使用:
fromEvent(this.inputName.nativeElement, 'keyup')
.pipe(
map((k: any) => k.target.value),
debounceTime(1000)
)
.subscribe(value => {
foo();
});
这是真正的 RXJS 方式,我已将 myArray.content
更改为 Observable
,因为这样您可以使用管道和映射。这将防止多个请求,更具体地说,它将在开始新搜索之前取消订阅以前的搜索。
searchedInput$ = new Subject<string>();
myArray: { content: Observable<any> } = {};
constructor(myService: any) {
this.myArray.content = this.searchedInput$.pipe(
distinctUntilChanged(),
debounceTime(400),
switchMap(input => myService.search(input)),
);
}
update(searchInput: string): void {
this.searchedInput$.next(searchInput);
}
您要找的是debounceTime。
它在发出任何东西之前等待 x 毫秒。
将它与其他运算符结合使用而不会使您的 API 过载将是一个不错的选择。
您的可观察对象看起来像
const search$ = fromEvent(search, 'input').pipe(
debounceTime(400), // Wait 400 MS before outputting
distinctUntilChanged(), // Only output unique values
map(event => event.target.value), // Extract the value of the search
switchMap((search) => service.doApi(search)) // SwitchMap to cancel a previous search if it wouldn't have completed
)
search$.subscribe() // These might leak. Keep them in an array and clean them up when the component unloads
搜索元素将是组件的 viewChild。
import { Component, ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { fromEvent, Subscription } from 'rxjs';
import { debounceTime, distinctUntilChanged, map, switchMap } from 'rxjs/operators';
@Component({
selector: 'app-component',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit, OnDestroy {
@ViewChild('yourInput', {static: true}) search: ElementRef;
searchSubscription: Subscription;
ngOnInit(): void {
const search$ = fromEvent(this.search.nativeElement, 'input').pipe(
debounceTime(400), // Wait 400 MS before outputting
distinctUntilChanged(), // Only output unique values
map((event: KeyboardEvent) => (event.target as HTMLInputElement).value), // Extract the value of the search
switchMap((search) => service.doApi(search)) // SwitchMap to cancel a previous search if it wouldn't have completed
) // Lives forever
this.searchSubscription = search$.subscribe()
}
ngOnDestroy(): void {
this.searchSubscription.unsubscribe()
}
}
我有一个 update()
方法,我用它在 table 和 update/filter 中搜索某些条目,用于输入字段中的每个击键。
我的目标是在每次击键后等待大约 400 毫秒,然后再将请求发送到后端,以避免出现太多无意义的请求。
目前我已经用 setTimeout()
函数实现了它,但我相信 RxJS 有更优雅的方法。
update(searchInput: string) {
setTimeout(() => {
this.myService.search(searchInput)
.subscribe((res) => {
this.myArray.content = res;
});
}, 400);
}
有人知道吗?
我在代码中留下了一些评论:
const search = fromEvent(searchInput, 'input').pipe(
debounceTime(1000), // Time in milliseconds between key events
distinctUntilChanged(), // If previous query is different from current
map(event => event.target.value) // get value,
filter(query => query) // if character length greater then 0,
tap(query => console.log(`About to make an API call with query: ${query}`)),
switchMap(getCars) // Your api call
);
search.subscribe(successCallback);
您可以执行以下操作:
在HTML中:
<input type="text" #myId="ngModel" [(ngModel)]="data" />
在你的组件中:
import {
debounceTime,
distinctUntilChanged
} from "rxjs/operators";
@ViewChild('myId', {static: true}) myControl: NgModel;
ngOnInit() {
this.myControl
.valueChanges // For each changes
.pipe(
debounceTime(400),
distinctUntilChanged()
)
.subscribe(() => ...)
}
尝试使用debounce()
和distinctUntileChanged()
:
handleFilterEvent = new Subject<any>();
ngOnInit(){
this.handleFilterEvent
.debounceTime(500)
.distinctUntilChanged()
.subscribe(value => {
this.myService.search(searchInput)
.subscribe((res) => {
this.myArray.content = res;
});
});
}
onSearchChange(value){
if(value) {
this.handleFilterEvent.next(value);
}
}
HTML:
<input type="text" class="form-control"
(input)="onSearchChange($event.target.value)">
您可以使用 fromEvent
和 Viewchild
只需引用 ViewChild 如下:
@ViewChild('yourInput') inputName: any;
那么你可以简单地使用:
fromEvent(this.inputName.nativeElement, 'keyup')
.pipe(
map((k: any) => k.target.value),
debounceTime(1000)
)
.subscribe(value => {
foo();
});
这是真正的 RXJS 方式,我已将 myArray.content
更改为 Observable
,因为这样您可以使用管道和映射。这将防止多个请求,更具体地说,它将在开始新搜索之前取消订阅以前的搜索。
searchedInput$ = new Subject<string>();
myArray: { content: Observable<any> } = {};
constructor(myService: any) {
this.myArray.content = this.searchedInput$.pipe(
distinctUntilChanged(),
debounceTime(400),
switchMap(input => myService.search(input)),
);
}
update(searchInput: string): void {
this.searchedInput$.next(searchInput);
}
您要找的是debounceTime。 它在发出任何东西之前等待 x 毫秒。 将它与其他运算符结合使用而不会使您的 API 过载将是一个不错的选择。
您的可观察对象看起来像
const search$ = fromEvent(search, 'input').pipe(
debounceTime(400), // Wait 400 MS before outputting
distinctUntilChanged(), // Only output unique values
map(event => event.target.value), // Extract the value of the search
switchMap((search) => service.doApi(search)) // SwitchMap to cancel a previous search if it wouldn't have completed
)
search$.subscribe() // These might leak. Keep them in an array and clean them up when the component unloads
搜索元素将是组件的 viewChild。
import { Component, ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { fromEvent, Subscription } from 'rxjs';
import { debounceTime, distinctUntilChanged, map, switchMap } from 'rxjs/operators';
@Component({
selector: 'app-component',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit, OnDestroy {
@ViewChild('yourInput', {static: true}) search: ElementRef;
searchSubscription: Subscription;
ngOnInit(): void {
const search$ = fromEvent(this.search.nativeElement, 'input').pipe(
debounceTime(400), // Wait 400 MS before outputting
distinctUntilChanged(), // Only output unique values
map((event: KeyboardEvent) => (event.target as HTMLInputElement).value), // Extract the value of the search
switchMap((search) => service.doApi(search)) // SwitchMap to cancel a previous search if it wouldn't have completed
) // Lives forever
this.searchSubscription = search$.subscribe()
}
ngOnDestroy(): void {
this.searchSubscription.unsubscribe()
}
}