rxjs-初体验

RxJS是一个主要用于处理异步程序的函数式编程库,可以把 RxJS想成处理异步行为的 Lodash,在angular中被大量使用,所以,了解它是必须的。

观察对象Observable

在介绍RxJs之前,我们有必要先了解下可观察对象(Observable)。

  1. 观察者(Observer)模式是一个软件设计模式,它有一个对象,称之为主体 Subject,负责维护一个依赖项。

  2. 可观察对象(Observable)是声明式的 —— 也就是说,虽然你定义了一个用于发布值的函数,但是在有消费者订阅它之前,这个函数并不会实际执行。 订阅之后,当这个函数执行完或取消订阅时,订阅者就会收到通知。

  3. 作为发布者,你创建一个 Observable的实例,其中定义了一个订阅者(subscriber)函数。 当有消费者调用 subscribe()方法时,这个函数就会执行。

  • 要执行所创建的可观察对象,并开始从中接收通知,你就要调用它的 subscribe()方法,并传入一个观察者(observer)。 这是一个 JavaScript对象,它定义了你收到的这些消息的处理器(handler)。 subscribe()调用会返回一个 Subscription对象,该对象具有一个 unsubscribe()方法。 当调用该方法时,你就会停止接收通知。

使用观察者模式大概就是这么个流程,创建可观察对象(Observable),定义订阅者(subscriber)函数处理逻辑并返回 Subscription对象,使用该对象的unsubscribe()方法取消订阅。

函数式编程

首先来与传统的方式作个对比,我们将使用两种不同的方式来实现至少间隔1秒打印鼠标在页面点击位置的功能:

传统写法:

ngOnInit(): void {
  let count = 0;
  const rate = 1000;
  let lastClick = Date.now() - rate;
  document.addEventListener('click', event => {
    if (Date.now() - lastClick >= rate) {
      count += event.clientX;
      console.log(count);
      lastClick = Date.now();
    }
  });
}

RxJs用法:

import {fromEvent} from 'rxjs';
import {map, scan, throttleTime} from 'rxjs/operators';
ngOnInit(): void {
  fromEvent(document, 'click').pipe(
    throttleTime(1000),
    map((event: MouseEvent) => event.clientX),
    scan((count, clientX) => count + clientX, 0)
  ).subscribe(
    count => console.log(count)
  );
}

tips: 使用RxJs,建议使用编辑器自动引入相应的资源(webstorm的自动导入比vscode好用)

从上面的简单的例子可以看出函数式编程的特点:

  1. 所有的逻辑均是通过一个个函数实现;

  2. 每一个函数都是一个纯函数(不改变数据源),会有一个返回值以供下一步操作使用;

Observable vs Promise

ObservablePromise的不同点:

  1. 可观察对象(Observable)是声明式的,在被订阅之前,它不会开始执行。Promise是在创建时就立即执行的。这让Observable可用于定义那些应该按需执行的逻辑;
class AppComponent {
    newPromise() {
      const p = new Promise(resolve => {
        console.log('initial a promise'); // 立即触发
      });
    }
    newObservable() {
      const o = new Observable(subscriber => {
        console.log('initial a newObservable'); // 不触发
      });
    }
}
  1. 串联,跟第一条类似,只有当调用subscribe方法时,才会执行所有管道函数;
class AppComponent {
  newPromise() {
    const p = new Promise(resolve => {
      resolve(['a', 'b', 'c']);
    }).then(res => {
      console.log('第一个then');
      return res;
    }).then(res => {
      console.log('第2个then');
      return res;
    }); // 打印出结果,被解析时自动完成
  }
  newObservable() {
    const o = new Observable(subscriber => {
      console.log('initial a newObservable');
      subscriber.next(['a', 'b', 'c']);
    }).pipe(
      map(res => {
        console.log('第一个map');
        return res;
      }),
      map(res => {
        console.log('第2个map');
        return res;
      })
    );  // 不能打印出结果,不订阅,pipe中的所有函数都不会触发
  }
}
  1. Observable可以手动取消;
const sub = interval(1000).subscribe(res => {
  console.log('interval', res);
});
class App {
  cancelObservable() {
    sub.unsubscribe();
  }
}

Observable vs 事件API

Observable的创建与取消:

// 创建点击事件 
const clicks$ = fromEvent(buttonEl, ‘click’); 
// 处理逻辑 
const subscription = clicks$.subscribe(e => console.log(‘Clicked’, e));
// 取消订阅 
subscription.unsubscribe();

事件API的创建与取消:

function handler(e) {
  console.log(‘Clicked’, e);
}
// 处理逻辑
button.addEventListener(‘click’, handler);
// 取消监听
button.removeEventListener(‘click’, handler);

Observable vs 数组

Observable会随时间生成值。数组是用一组静态的值创建的。某种意义上,Observable是异步的,而数组是同步的。

数组的concat方法:

const arr1 = ['a', 'b', 'c'];
const arr2 = [1, 2, 3];
console.log(arr1.concat(arr2)); // 众所周知,打印出:["a", "b", "c", 1, 2, 3]

Observableconcat方法:

import {concat, from} from 'rxjs';

const arr1$ = from(['a', 'b', 'c']);
const arr2$ = from([1, 2, 3]);
concat(arr1$, arr2$).subscribe(res => {
  console.log(res); // 将会依次打印:"a", "b", "c", 1, 2, 3每个元素
});

总结

  1. RxJS是一个主要用于处理异步程序的函数式编程库;

  2. 可观察对象(Observable)没有被订阅就不会执行;

  3. 函数式编程让代码逻辑更加清晰。

(tips:从我现在的水平来讲,RxJs对于处理异步数据是很有用的,特别是对数据流时间节点要求较高的操作是会比Promise更加灵活可控的。而且在angular中,随处可见Rxjs,所以,学好它非常有必要,是必须掌握的技能。这个文档也可以看看:https://blog.jerry-hong.com/series/rxjs/thirty-days-RxJS-00)。

欢迎关注我的公众号,公众号将第一时间更新angular教程:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yanyi24

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值