Javascript 使用rjxs而不是setTimeout函数订阅更优雅的方式?
我有一个Javascript 使用rjxs而不是setTimeout函数订阅更优雅的方式?,javascript,angular,typescript,rxjs,rxjs6,Javascript,Angular,Typescript,Rxjs,Rxjs6,我有一个update()方法,用它搜索表中的某些条目,并更新/过滤输入字段中每个击键的条目 我的目标是在每次击键后等待大约400毫秒,然后将请求发送到后端,这样我就避免了太多无意义的请求 目前我已经用setTimeout()函数实现了它,但我确信RxJS有一种更优雅的方式 update(searchInput: string) { setTimeout(() => { this.myService.search(searchInput) .subscri
update()
方法,用它搜索表中的某些条目,并更新/过滤输入字段中每个击键的条目
我的目标是在每次击键后等待大约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" />
}尝试使用debounce()
和distinctuntellechange()
:
handleFilterEvent=新主题();
恩戈尼尼特(){
这是handleFilterEvent
.debounceTime(500)
.distinctUntilChanged()
.subscribe(值=>{
this.myService.search(searchInput)
.订阅((res)=>{
this.myArray.content=res;
});
});
}
onSearchChange(值){
如果(值){
this.handleFilterEvent.next(值);
}
}
HTML:
您可以使用
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
更改为可观察的
,因为这样可以使用管道和映射。这将防止多个请求,更具体地说,它将在开始新的搜索之前取消订阅以前的搜索
searchedInput$=新主题();
myArray:{content:Observable}={};
构造函数(myService:any){
this.myArray.content=this.searchedInput$.pipe(
distinctUntilChanged(),
去BounceTime(400),
switchMap(输入=>myService.search(输入)),
);
}
更新(搜索输入:字符串):无效{
this.searchedInput$.next(searchInput);
}
您要找的是。
它等待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()
}
}
您需要使用debounce而不是。如果您使用管道语法并为搜索请求添加
switchMap
,这将是完美的。感谢你的帮助。但通过这种方式,我得到了错误:“属性‘target’不存在于由map((event)=>event.target.value)生成的类型‘unknown.ts(2339)’。fromEvent
数据类型当前为类型{}。我已经更新了我的答案,将事件类型缩小为keyboardEvent,因为dom中实际上缺少InputEvent类型。typingsNow它说:错误错误:未捕获(承诺中):类型错误:无法读取Undefinedah的属性“nativeElement”,新手错误。nativeElement仅在ngOnInit中可用。让我更新一下我的回答,我还认为这与生命周期有关。Thnx。
fromEvent(this.inputName.nativeElement, 'keyup')
.pipe(
map((k: any) => k.target.value),
debounceTime(1000)
)
.subscribe(value => {
foo();
});
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
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()
}
}