Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/399.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何使用rxjs在angular2中实现输入keyup事件的去抖动服务_Javascript_Angular_Typescript_Rxjs_Rxjs5 - Fatal编程技术网

Javascript 如何使用rxjs在angular2中实现输入keyup事件的去抖动服务

Javascript 如何使用rxjs在angular2中实现输入keyup事件的去抖动服务,javascript,angular,typescript,rxjs,rxjs5,Javascript,Angular,Typescript,Rxjs,Rxjs5,我正在尝试在输入键向上事件时调用服务 HTML <input placeholder="enter name" (keyup)='onKeyUp($event)'> 从浏览器的“网络”选项卡中可以发现,它正在对每个加钥匙事件调用加钥匙功能(正如它应该做的那样),但我试图实现的是每次服务调用之间的1秒去盎司时间。此外,如果我移动箭头键move,则会触发该事件 好吧,这是一个基本的去抖器 ngOnInit ( ) { let inputBox = this.myInpu

我正在尝试在输入键向上事件时调用服务

HTML

<input placeholder="enter name" (keyup)='onKeyUp($event)'>
从浏览器的“网络”选项卡中可以发现,它正在对每个加钥匙事件调用加钥匙功能(正如它应该做的那样),但我试图实现的是每次服务调用之间的1秒去盎司时间。此外,如果我移动箭头键move,则会触发该事件


好吧,这是一个基本的去抖器

ngOnInit ( ) {
        let inputBox = this.myInput.nativeElement;
        let displayDiv = this.myDisplay.nativeElement;

        let source = Rx.Observable.fromEvent ( inputBox, 'keyup' )
            .map ( ( x ) => { return x.currentTarget.value; } )
            .debounce ( ( x ) => { return Rx.Observable.timer ( 1000 ); } );

        source.subscribe (
            ( x ) => { displayDiv.innerText = x; },
            ( err ) => { console.error ( 'Error: %s', err ) },
            () => {} );
    }
}

如果您设置了两个指定的视图子项(输入和显示),您将看到去盎司工作。不确定这是否对你的工作没有任何作用,但这个基本形式是(据我所知)直接的去Bounce方法,我经常使用这个起点,内部文本集只是一个示例,它可以进行服务调用或其他任何你需要它做的事情

我建议您查看Angular2教程,该教程提供了一个与您所问内容类似的清晰解释示例


所以这个链确实是正确的,但问题是您正在创建一个可观察的,并在每个
keyup
事件中订阅它。这就是它多次打印相同值的原因。只是有多个订阅,这不是您想要做的

显然有更多的方法可以正确执行,例如:

@Component({
  selector: 'my-app',
  template: `
    <div>
      <input type="text" (keyup)='keyUp.next($event)'>
    </div>
  `,
})
export class App implements OnDestroy {

  public keyUp = new Subject<KeyboardEvent>();

  private subscription: Subscription;

  constructor() {
    this.subscription = this.keyUp.pipe(
      map(event => event.target.value),
      debounceTime(1000),
      distinctUntilChanged(),
      mergeMap(search => of(search).pipe(
        delay(500),
      )),
    ).subscribe(console.log);
  }

  ngOnDestroy(): void {
    this.subscription.unsubscribe();
  }
}
@组件({
选择器:“我的应用程序”,
模板:`
`,
})
导出类应用程序实现OnDestroy{
public keyUp=新主题();
私人认购:认购;
构造函数(){
this.subscription=this.keyUp.pipe(
映射(event=>event.target.value),
去BounceTime(1000),
distinctUntilChanged(),
合并映射(搜索=>of(搜索).pipe(
延迟(500),
)),
).subscribe(console.log);
}
ngOnDestroy():void{
this.subscription.unsubscripte();
}
}
查看更新的演示:


2019年1月:RxJS 6更新版

@marlin提供了一个很好的解决方案,它在angular 2.x中运行良好,但在angular 6中,他们已经开始使用RxJS 6.0版本,该版本的语法略有不同,因此这里是更新的解决方案

import {Component} from '@angular/core';
import {Observable, of, Subject} from 'rxjs';
import {debounceTime, delay, distinctUntilChanged, flatMap, map, tap} from 'rxjs/operators';

@Component({
    selector: 'my-app',
    template: `
        <div>
            <input type="text" (keyup)='keyUp.next($event)'>
        </div>
     `,
})
export class AppComponent {
    name: string;

    public keyUp = new Subject<string>();

    constructor() {
        const subscription = this.keyUp.pipe(
            map(event => event.target.value),
            debounceTime(1000),
            distinctUntilChanged(),
            flatMap(search => of(search).pipe(delay(500)))
        ).subscribe(console.log);
    }
}
从'@angular/core'导入{Component};
从“rxjs”导入{可观察的,of的,Subject};
从“rxjs/operators”导入{debounceTime、delay、distinctUntilChanged、flatMap、map、tap};
@组成部分({
选择器:“我的应用程序”,
模板:`
`,
})
导出类AppComponent{
名称:字符串;
public keyUp=新主题();
构造函数(){
const subscription=this.keyUp.pipe(
映射(event=>event.target.value),
去BounceTime(1000),
distinctUntilChanged(),
平面图(搜索=>of(搜索).pipe(延迟(500)))
).subscribe(console.log);
}
}

指定RxJS版本,因为版本4和版本5有很多不同。这一定是RxJS 5,因为他使用的是Angular2。您现在所做的是正确的,所以您不知道如何调用服务或什么?@martin我可以调用服务。但我面临的问题是对服务器的调用太多。在每一次调高事件中,都会有一个去盎司效应。但在去盎司时间之后,服务会被调用多次。也就是说,如果在去盎司时间之间有10个键启动事件,则该服务被调用10次。另外,如果我使用相同的搜索词移动左右箭头键,则会调用该服务(这是不需要的)。@DDRamone“rxjs”:“5.0.0-beta.12”这很有效,但有点误导。keyUp不是主题类型。如果您想要主题,您必须在输入
(keyup)='keyup.next($event.target.value)
中指定如果用户点击“Enter”,您希望在不等待退出的情况下执行What-ever逻辑。有没有办法忽略谴责?@BlackEagle只需为keyup.enter事件添加与模板中相同的函数,例如(keyup.enter)=“console.log($event.target.value)”错误TS2339:类型“string”上不存在属性“target”。@FrancescoBorzì您可以使用
映射((event:any)=>(event.target.value),
或设置事件的类型
import {Component} from '@angular/core';
import {Observable, of, Subject} from 'rxjs';
import {debounceTime, delay, distinctUntilChanged, flatMap, map, tap} from 'rxjs/operators';

@Component({
    selector: 'my-app',
    template: `
        <div>
            <input type="text" (keyup)='keyUp.next($event)'>
        </div>
     `,
})
export class AppComponent {
    name: string;

    public keyUp = new Subject<string>();

    constructor() {
        const subscription = this.keyUp.pipe(
            map(event => event.target.value),
            debounceTime(1000),
            distinctUntilChanged(),
            flatMap(search => of(search).pipe(delay(500)))
        ).subscribe(console.log);
    }
}