rxjs实战场景使用

856 阅读2分钟

响应式编程是一种面向数据流和变更传播的异步编程范式。RxJS是一个使用可观察对象进行响应式编程的库,它让组合异步代码和基于回调的代码变得更简单,下面展示业务功能在rxjs中是怎么实现的

竟态问题

比如查询按钮,点击查询时要是上一次查询没有结束直接取消,只请求当前查询

    import { fromEvent } from 'rxjs';
    import { ajax } from 'rxjs/ajax';
    const queryBtnEle = document.getElementById('query-btn') as HTMLInputElement;
    fromEvent(queryBtnEle, 'click')
      .pipe(switchMap(target => ajax('https://api.github.com/users?per_page=5')))
      .subscribe(data => {
        console.log('请求数据', data);
    });

与之相对的exhaustMap操作符表示前一个没有结束,当前的取消

输入提示建议

可观察对象可以简化输入提示建议的实现方式。典型的输入提示要完成一系列独立的任务:

  • 移除输入值前后的空白字符,并确认它达到了最小长度
  • 防抖(这样才能防止连续按键时每次按键都发起 API 请求,而应该等到按键出现停顿时才发起)
  • 如果输入值没有变化,则不要发起请求(比如按某个字符,然后快速按退格)
  • 如果已发出的 AJAX 请求的结果会因为后续的修改而变得无效,那就取消它
import { fromEvent } from 'rxjs';
import { ajax } from 'rxjs/ajax';
import { debounceTime, distinctUntilChanged, filter, map, switchMap } from 'rxjs/operators';

const searchBox = document.getElementById('search-box') as HTMLInputElement;

const typeahead = fromEvent(searchBox, 'input').pipe(
  map(e => (e.target as HTMLInputElement).value),
  filter(text => text.length > 2), // 过滤数据
  debounceTime(10), // 防抖
  distinctUntilChanged(), // 数据值没变不发送数据
  switchMap(searchTerm => ajax(`/api/endpoint?search=${searchTerm}`)) // 已发数据没来就取消
).subscribe(data => {
    console.log('查询提示数据', data)
)

合并数据

多个AJAX请求都完成才返回合并后的数据

import { forkJoin } from 'rxjs';
import { ajax } from 'rxjs/ajax';
forkJoin([ajax(`/api1`), ajax(`/api2`), ajax(`/api3`)]).subscribe(result => {
  const [res1, res2, res3] = result;
});

combineLatest,zip 是相关合并数据场景

防抖和节流

节流如下

import { throttleTime } from 'rxjs/operators';
const scrollEle = document.getElementById('scroll-content');
const typeahead = fromEvent(scrollEle, 'scroll').pipe(throttleTime(100)); 
typeahead.subscribe(event => {
 // 滚动时每100毫秒取一个数据
  console.log('滚动事件对象', event); 
});

防抖在输入场景中使用 如上面的'输入提示建议'

debounce, throttle 可以自定义防抖和节流

缓冲

游戏技能组合键

import { bufferTime, filter } from 'rxjs/operators';

fromEvent(document, 'keypress')
  .pipe(
    bufferTime(100), // 100毫秒内的按键数据变成数组向下传
    filter((res: KeyboardEvent[]) => {
      if (res.length >= 3) {
        return res.every(val => 'abc'.indexOf(val.key) !== -1);
      }
      return false;
    })
  )
  .subscribe(() => {
    console.log('放abc组合按键技能');
  });

还有如: 群聊天设置消息缓冲,太多人聊天每条数据一来马上渲染,消息一下来太多很可能变卡,对消息缓冲一个时间段来的消息一起渲染,有效提高用户体验