rxjs中的throttle、throttleTime、debounce、debounceTime、audit、audtiTime

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zgrbsbf/article/details/87921732

1、debounceTime

Emits a value from the source Observable only after a particular time span has passed without another source emission.

大意是,只有在指定的时间间隔内没有产生另外的数据的时候,之前产生的数据才能被observable发射出来。marble diagram如下所示:
在这里插入图片描述
a产生出来20ms后没有产生别的数据,订阅者可以得到a。b产生出来20ms内产生了新的数据c,b被忽略。c产生之后20ms内没有产生新数据,订阅者可以得到c…
试着写一个demo试试:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    html {
      height: 100vh;
    }
  </style>
  <script src="https://cdn.bootcss.com/rxjs/6.4.0/rxjs.umd.min.js"></script>
</head>
<body>
<script>
  const {fromEvent} = rxjs;
  const {debounceTime } = rxjs.operators;
  const clicks = fromEvent(document, 'click');
  const result = clicks.pipe(debounceTime(1000));
  result.subscribe(x => console.log(x));
</script>
</body>
</html>

不断的在页面上点击,如果某个点击之后的1000内没有新的点击,则该点击会被订阅到。

2、debounce

Emits a value from the source Observable only after a particular time span (determined by another Observable) has passed without another source emission.

marble diagram如下:
在这里插入图片描述

和debounceTime相比,多出了括号里面的部分。observable A产生数据经过debounce处理后,产生的数据能否被订阅到,由另外一个observable B决定。
写一个demo试一下:

2.1 第二个事件控制第一个事件的数据产出

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    html {
      height: 100vh;
    }
    div{
      height: 100px;
      background:red;
    }
    #bbb{
      background: blue;
    }
  </style>
  <script src="https://cdn.bootcss.com/rxjs/6.4.0/rxjs.umd.min.js"></script>
</head>
<body>
<div id="aaa"></div>
<div id="bbb"></div>
<script>
  const {fromEvent} = rxjs;
  const {debounce} = rxjs.operators;
  const clicksaaa = fromEvent(document.querySelector('#aaa'), 'click');
  const clicksbbb = fromEvent(document.querySelector('#bbb'), 'click');
  const result = clicksaaa.pipe(debounce(() => clicksbbb));
  result.subscribe(x => console.log(x));
</script>
</body>
</html>

效果如下gif所示:
在这里插入图片描述
不断的点击红色的div,订阅者拿不到数据,点击一下蓝色的div,订阅者才能拿到数据。点击蓝色div这个事件被封装成了一个observable,他就像是一个开关一样,点一下就打开,不过只能有之前最近的时间内产生的那个数据才能通过。

2.2 最近点击之后的一秒后发射数据

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    html {
      height: 100vh;
    }
    div{
      height: 100px;
      background:red;
    }
  </style>
  <script src="https://cdn.bootcss.com/rxjs/6.4.0/rxjs.umd.min.js"></script>
</head>
<body>
<div id="aaa"></div>
<script>
  const {fromEvent, interval,timer } = rxjs;
  const {debounce} = rxjs.operators;
  const clicksaaa = fromEvent(document.querySelector('#aaa'), 'click');
  let k = 0;
  document.querySelector('#aaa').addEventListener('click',()=>console.log(k= Date.now()));
  // const result = clicksaaa.pipe(debounce(() => interval(2000))); // 我也不知道这个和下面这个有什么区别
  const result = clicksaaa.pipe(debounce(() => timer(1000)));
  result.subscribe(x => console.log(Date.now()-k ));
</script>
</body>
</html>

在这里插入图片描述

3、throttleTime

Emits a value from the source Observable, then ignores subsequent source values for duration milliseconds, then repeats this process.

大意是,发射第一个数据出来之后,之后发射的频率受duration影响,每次发射之后的duration时间之内不会发射出来新的数据。

marble diagram如下:
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    html {
      height: 100vh;
    }
  </style>
  <script src="https://cdn.bootcss.com/rxjs/6.4.0/rxjs.umd.min.js"></script>
</head>
<body>
<script>
  const {fromEvent} = rxjs;
  const {throttleTime} = rxjs.operators;
  let k = 0;
  const clicks = fromEvent(document, 'click');
  const result = clicks.pipe(throttleTime(1000));
  result.subscribe(() => {
    const i = Date.now();
    if(k){
      console.log(i-k);
    }
    k = i;
  });
</script>
</body>
</html>

在这里插入图片描述

4、throttle

Emits a value from the source Observable, then ignores subsequent source values for a duration (determined by another Observable), then repeats this process.

throttle emits the source Observable values on the output Observable when its internal timer is disabled,
and ignores source values when the timer is enabled.
Initially, the timer is disabled.
As soon as the first source value arrives, it is forwarded to the output Observable,
and then the timer is enabled by calling the durationSelector function with the source value, which returns the “duration” Observable.
When the duration Observable emits a value or completes, the timer is disabled, and this process repeats for the next source value.

括号里面的是比throttleTime多出的部分。
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    html {
      height: 100vh;
    }
    div {
      height: 100px;
      background: red;
    }
    #bbb {
      background: blue;
    }
  </style>
  <script src="https://cdn.bootcss.com/rxjs/6.4.0/rxjs.umd.min.js"></script>
</head>
<body>
<div id="aaa"></div>
<div id="bbb"></div>
<script>
  const {fromEvent} = rxjs;
  const {throttle} = rxjs.operators;
  const clicksaaa = fromEvent(document.querySelector('#aaa'), 'click');
  const clicksbbb = fromEvent(document.querySelector('#bbb'), 'click');
  const result = clicksaaa.pipe(throttle(() => clicksbbb));
  result.subscribe(x => console.log(x));
</script>
</body>
</html>

在这里插入图片描述
可以这样分析上面的结果:
1.开始的时候,内部timer是disabled状态,点击红色的div会有打印输出;之后内部timer变成enabled状态,接下来的点击被忽略。
2.但是当点击了蓝色的div之后,throttle里面的那个observable有了产出,内部timer又变成disabled状态。
重复1和2

5、auditTime

Ignores source values for duration milliseconds, then emits the most recent value from the source Observable, then repeats this process.

auditTime is similar to throttleTime, but emits the last value from the silenced time window, instead of the first value.

在这里插入图片描述
这个operator和throttleTime的区别,

<script src="https://cdn.bootcss.com/rxjs/6.4.0/rxjs.umd.min.js"></script>
<script>
  const {fromEvent, interval} = rxjs;
  const {auditTime, throttleTime} = rxjs.operators;
  interval(500).pipe(auditTime(1000)).subscribe(x => console.log('auditTime', x));
  interval(500).pipe(throttleTime(1000)).subscribe(x => console.log('throttleTime', x));
</script>

在这里插入图片描述

6、audit

Ignores source values for a duration determined by another Observable, then emits the most recent value from the source Observable, then repeats this process.

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    html {
      height: 100vh;
    }
    div {
      height: 100px;
      background: red;
    }
    #bbb {
      background: blue;
    }
  </style>
  <script src="https://cdn.bootcss.com/rxjs/6.4.0/rxjs.umd.min.js"></script>
</head>
<body>
<div id="aaa"></div>
<div id="bbb"></div>
<script>
  const {fromEvent} = rxjs;
  const {audit} = rxjs.operators;
  const clicksaaa = fromEvent(document.querySelector('#aaa'), 'click');
  const clicksbbb = fromEvent(document.querySelector('#bbb'), 'click');
  const result = clicksaaa.pipe(audit(() => clicksbbb));
  result.subscribe(x => console.log(x));
</script>
</body>
</html>

跑一下代码,效果如下:
在这里插入图片描述
可以这么分析下:
audit is similar to throttle, but emits the last value from the silenced time window, instead of the first value. audit emits the most recent value from the source Observable on the output Observable as soon as its internal timer becomes disabled, and ignores source values while the timer is enabled. Initially, the timer is disabled.
As soon as the first source value arrives, the timer is enabled by calling the durationSelector function with the source value, which returns the “duration” Observable.
When the duration Observable emits a value or completes, the timer is disabled,
then the most recent source value is emitted on the output Observable, and this process repeats for the next source value.

1.开始的时候,内部timer是disabled状态;第一次点击红色的div的时候会激活内部timer到enabled状态;这个时候可以再点击红色div任意次数,可以看到到目前为止控制台还是没有输出。
2.但是当点击了蓝色的div之后,audit里面的内部timer又变成disabled状态,结果是最近的红色div的点击被输出到控制台
重复1和2

在前端,有人称类似的思想的实现为节流和防抖。

参考文献:
https://rxjs.dev/api/operators/throttle
http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-throttleTime
https://mp.weixin.qq.com/s/I5IpQo0sQGFbhcR8HNaPJQ

猜你喜欢

转载自blog.csdn.net/zgrbsbf/article/details/87921732