React magic - useEvent

2024/03/02 React 共 3194 字,约 10 分钟

1、可观察者Observable

1.1、Observable核心要点

  • Observable声明的订阅主体,在调用订阅之前并不会执行
  • 可以添加无限个next,但每个next在订阅声明后,都会触发一次订阅执行
  • next声明的顺序并不代表最终订阅消费执行的顺序,会受到异步代码干扰
  • 只有手动确认了complete才会调用complete功函数

    • complete之后,如果声明了unSub,则会自动调用unSub函数
    • add添加的事件会在unSub之前调用
  • error和complete是互斥的,只会有一个执行

    • error会终止后续的订阅事件
  • 订阅本身会返回一个subscription,可以简单的调用unsubscribe事件

1.2、简单的使用范式

2.1.1、极简使用范式

const observable = new Observable((subscriber) => {
  subscriber.next(1)
  subscriber.next(2)
  subscriber.next(3)
  return () => {
    console.log(4);
  }
})
const unSub = observable.subscribe(val => {
  console.log('val: ', val); // 订阅调用三次:1, 2, 3
})
unSub.add(() => {
  console.log(5);
})
unSub.unsubscribe() // result: 1, 2, 3, 4, 5

2.1.2、定制化使用范式

const observable = new Observable((subscriber) => {
  console.log('Observable声明的内容,在调用之前不会执行。01')
  subscriber.next('可以添加无限个next,每个next都会产生一次订阅消费,会导致subscribe的next执行多次。02')
  setTimeout(() => {
    subscriber.next('这里是异步执行。03')
    subscriber.complete() // 订阅确认执行完成后,如果返回了unsub fn,则会自动执行unsud fn
  }, 1000)
  subscriber.next('next声明的顺序并不代表订阅执行的顺序,这里是同步的声明,会优先执行。04')
  subscriber.add(() => {
    console.log('通过add添加的方法会在unsub之前执行。05');
  })
  subscriber.error('抛出错误会导致后续的订阅事件取消,订阅终止。10') // 此行代码不注释时:07, 01, 02, 04, 10, 05, 06, 09。不会执行:03, 08
  return () => {
    console.log('可选的订阅解除时执行的内容。06')
  }
})
console.log('在订阅消费之前,只是一个声明,所以这里优先执行。07')
observable.subscribe({
  next(nextData) {
    console.log('nextData: ', nextData);
  },
  error(err) {
    console.log('err: ', err);
  },
  complete() {
      console.log('所有订阅成功执行完成后执行。08');
  },
})
console.log('同步执行。09'); // result: 07, 01, 02, 04, 09, 03, 08, 05, 06

2、观察者Observer

Obersver即订阅消费的主体,有两种表现形式

2.1、声明式Observer

  • error和complete为可选声明
const observer = {
  next(nextValue) {
    console.log('do something with nextValue');
  },
  error(err) {
    console.log('do something when got an error');
  },
  complete() {
    console.log('Observer got a complete notigication');
  },
}

2.2、极简Observer

observable.subscribe((nextValue) => {
  console.log('do something with nextValue:', nextValue);
})

3、操作符Operators

4、订阅Subscription

5、主体Subjects

  • 主体Subjects类似于EventEmitter,声明监听器以后,通过next发射参数到监听器进行执行
  • Subjects可以多播,即可以声明多个注册器,一次next会有多次响应
  • 它类似于JS中的addEventlistener,一次注册以后,通过next触发事件
  • 原型方法有:next、error、complete等
  • 注:任何在监听器注册订阅之前发出的next都会被忽略
const subject = new Subject()
subject.next(1) // 这里并不会执行,因为监听器尚未注册
subject.subscribe(val => {
  console.log('subscriber1: ', val);
})
subject.subscribe(val => {
  console.log('subscriber2: ', val);
})
subject.next(2) // 多播,共有两个注册订阅监听器
/* 
  result: 
    subscriber1: 2 
    subscriber2: 2
 */

[1]

  • fromPromise变更为from - https://github.com/kadoshms/ionic2-autocomplete/issues/169
from(Promise.resolve(11)).subscribe(x => console.log(x)); // 11
  • of和range一样,都是Cold Obervable,即每次订阅都谁重复吐出同样的一组数据,可以反复使用。
    • 它是同步的,会一口气吐出全部的数据
    • 然后调用Observer的complete函数
const source$ = of(1)
// 注意,这里通过参数规定err和complete调用的方式已经启用,转为为声明式的Observer Object
source$.subscribe(x => console.log(x), null, () => {console.log('complete')}); // 1 complete
source$.subscribe(x => console.log(x)); // 1
  • repeat依赖于Observable对象的complete完结,完结以后,才会repeat下一次调用
const observable = new Observable(subscribe => {
  for (let i = 0; i < 3; i++) {
    subscribe.next(i)
  }
  // subscribe.complete() // 如果此行代码被注释掉,则永远不会发生repeat
})
observable.pipe(repeat(2)).subscribe(v => {
  console.log('v: ', v); // 1,2,3
})
  • 使用throwError替换throw关键字
  • 手动控制takeUntil终止
const notifer$ = new Subject()
interval(1000).pipe(takeUntil(notifer$)).subscribe(v => {
  console.log('v: ', v);
}, err => {
  console.log('err: ', err);
})
setTimeout(() => {
  notifer$.next(1)
  notifer$.complete()
}, 4000)

Search

    Table of Contents