【问题标题】:Don't allow function to be executed for a certain time after it has been executed不允许函数在执行后的一段时间内执行
【发布时间】:2020-07-31 09:30:56
【问题描述】:

我想在一个函数运行后延迟它,这样它就不能在这段时间内再次运行。

一个接近它的例子:

ngOnInit() {
 setInterval(() => this.functionWithTimeLimit(), 500);
}

functionWithTimeLimit() {
 if(allowedToRun){
  console.log('Run me every 2 seconds at most');

  allowedToRun = false;
  setTimeout(() => allowedToRun = true, 2000); // Allow to execute this function again after two seconds
 }
}

但我确信使用 rxjs 可能有更好的方法来做到这一点。我怎么能这样做?

【问题讨论】:

  • 看看这个问题中不同的“节流”方法:Simple throttle in js
  • 油门是我一直在寻找的术语,谢谢!它把我带到了这个页面:telerik.com/blogs/…。这让我明白我真的需要油门而不是去抖动。

标签: javascript angular rxjs observable


【解决方案1】:

有多种方法可以做到这一点。

一种方法是创建一个 RxJS Subject 并路由函数调用以从中发出通知。在订阅这个 observable 时,你可以使用 RxJS throttleTime 操作符来忽略指定时间内的后续排放。

试试下面的

控制器

import { Subject } from 'rxjs';
import { throttleTime, takeUntil } from 'rxjs/operators';

export class AppComponent implements OnInit, OnDestroy {
  completed$ = new Subject<any>();
  trigger$ = new Subject<any>();

  constructor() { }

  functionWithTimeLimit() {
    console.log('called functionWithTimeLimit');
  }

  ngOnInit() {
    this.trigger$.pipe(
      throttleTime(2000),             // <-- ignore notifications for 2s after an emission
      takeUntil(this.completed$)      // <-- use to close the subscription
    ).subscribe(this.functionWithTimeLimit.bind(this));
  }

  ngOnDestroy() {
    this.completed$.next();           // <-- close impending subscriptions 
  }
}

模板

<button (mouseup)="trigger$.next()">Trigger function</button>

工作示例:Stackblitz

在上面的例子中,假设最初按下按钮应该直接触发该功能。但是现在我们在按下按钮时发出 observable 并在它的订阅中触发函数。

更新:throttleTimedebounceTime 之间的区别

throttleTime 将在单个通知后暂停后续通知一段固定的时间。

var { fromEvent } = rxjs;
var { throttleTime, map } = rxjs.operators;

var inputBox = document.getElementById('search');
var displayBox = document.getElementById('display');

fromEvent(inputBox, 'keyup').pipe(
  map(event => event.currentTarget.value),
  throttleTime(2000),
).subscribe(value => displayBox.innerHTML = value);
<script src="https://unpkg.com/rxjs@6.4.0/bundles/rxjs.umd.min.js"></script>

Keep on typing. It will render the value continuously every 2 sec.<br><br>

<input type="text" id="search" />
<p id="display"></p>

debounceTime 将在每次通知后暂停后续通知一段时间。

var { fromEvent } = rxjs;
var { debounceTime, map } = rxjs.operators;

var inputBox = document.getElementById('search');
var displayBox = document.getElementById('display');

fromEvent(inputBox, 'keyup').pipe(
  map(event => event.currentTarget.value),
  debounceTime(2000),
).subscribe(value => displayBox.innerHTML = value);
<script src="https://unpkg.com/rxjs@6.4.0/bundles/rxjs.umd.min.js"></script>

Keep on typing. It'll render only after 2 seconds after the typing stops.<br><br>

<input type="text" id="search" />
<p id="display"></p>

【讨论】:

  • 谢谢,这就是我要找的!在时间跨度内无法再次调用该函数,并且与去抖动不同,再次调用时时间跨度不会重置。
【解决方案2】:

您可以使用intervaldebounceTime 来更好地处理这种情况。

在适当的时候注意unsubscribe(可能在ngOnDestroy

我有一个工作示例,不确定是否是您的情况,但您可以使用它。 StackBlitz

【讨论】:

  • 谢谢,它很接近,但它不是我要找的。我认为节流会更好地满足我的需求。
猜你喜欢
  • 2020-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-16
  • 2015-12-21
  • 1970-01-01
  • 1970-01-01
  • 2017-02-03
相关资源
最近更新 更多