Angular文档 Observable&Rxjs 部分解读

读了两天angular文档Observable&Rxjs部分的内容后,最突出的感受就是这玩意不是给人看的。写文档的人要么就是精通一切的大佬,看着我们绞尽脑汁学习也无法理解的样子在屏幕前偷笑;要么就是个蠢蛋,他也不知道开发团队写出来的是个什么东西,把他们给的例子往文档里一塞就完事了。或许是我太菜,但是最难框架Angular+最新技术Rxjs+最凌乱难懂的Angular文档,这学习成本真是名不虚传

我只能以目前的水平按自己的理解尽量解读一下这一页的教程https://www.angular.cn/guide/observables

Observable是promise的升级,大概意思就是创建一个Observable实例。Observable构造函数的参数是一个订阅者subscriber函数A,这个函数A有参数观察者observer,observer对象有属性next, error, complete函数,函数体定义了如何获取值。next函数定义获取之后如何处理值。调用observable的 subscribe() 方法,需要传入一个观察者对象observer。每次调用subscribe,函数A都会执行。

文档给的入门示例如下(节省篇幅去掉了注释)


const locations = new Observable((observer) => {
  const {next, error} = observer;
  let watchId;

  if ('geolocation' in navigator) {
    watchId = navigator.geolocation.watchPosition(next, error);
  } else {
    error('Geolocation not available');
  }

  return {unsubscribe() { navigator.geolocation.clearWatch(watchId); }};
});
 
const locationsSubscription = locations.subscribe({
  next(position) { console.log('Current Position: ', position); },
  error(msg) { console.log('Error Getting Location: ', msg); }
});

setTimeout(() => { locationsSubscription.unsubscribe(); }, 10000);

 第一个示例,就能看到const、let、in、对象的解构赋值、箭头函数、不知道什么作用的api,怎么复杂怎么来,生怕我们学会。甚至竟然还有错误。

const {next, error} = observer;  这行的作用相当于 const next=observer.next ;可是console.log(next)就能发现,next函数的内容是

ƒ (value) {
        if (!this.isStopped) {
            this._next(value);
        }
    }

已经不是你写的next函数的内容!而是指向observer的另一个函数!这个navigator.geoLocation对象要这么一个函数有意义?肯定没有!this引用的对象也已经改变,observer.next中this指向observer,navigator.geolocation.watchPosition(next, error)已经指向了geolocation。

所以你惊奇的发现,除了这个例子,const {next, error} = observer这种用法再也没有出现过,下面的例子都是observer.next。

 

接下的有点难但勉强能看懂。直到这个例子

function fromEvent(target, eventName) {
  return new Observable((observer) => {
    const handler = (e) => observer.next(e);

    // Add the event handler to the target
    target.addEventListener(eventName, handler);

    return () => {
      // Detach the event handler from the target
      target.removeEventListener(eventName, handler);
    };
  });
}

const ESC_KEY = 27;
const nameInput = document.getElementById('name') as HTMLInputElement;

const subscription = fromEvent(nameInput, 'keydown')
  .subscribe((e: KeyboardEvent) => {
    if (e.keyCode === ESC_KEY) {
      nameInput.value = '';
    }
  });

 我来分析分析这个例子到底是在干嘛。

最终达到的效果是按ESC键input输入框清空。一般情况下我们想实现这个功能只需要这样做

    document.querySelector('#name').addEventListener('keydown', function(ev){
      if(ev.keyCode==27){
        (ev.target as HTMLInputElement).value='';
      }
    })

 可是angular他有自己的想法。他不想这样,觉得太简单了,必须利用observable来实现。正如官网所说,"创建一个用来发布事件的可观察对象"

发布事件就是observer接收一个事件,next函数的参数是一个事件。事件就是一个对象,即证明一下我们强大的observable不仅可以发布number,也可以发布对象

为了满足observer接收一个事件,这样写

    const observer1={
      next(ev: any){
        if(ev.keyCode == 65){
          (document.querySelector('#name') as HTMLInputElement).value='';
        }
      }
    }

然后observable

    const mmm=new Observable((observer) => {
      function handler(e){
        observer.next(e);
      }
      document.querySelector('#name').addEventListener('keydown', handler);
      return ()=>{
        document.querySelector('#name').removeEventListener('keydown', handler);
      }
    });

这里为什么要加一个handler?如果observer.next已经不是我们写的observer1中的next了,已经指向了observer的其他属性,例如_next。如果内容还是我们写的那个函数,则直接document.querySelector('#name').addEventListener('keydown', observer.next);就行。但是这个参数被处理过了,所以不行。next不能脱离observer自己行动。

最后,只需要加一行

 mmm.subscribe(observer1);

 就能实现按ESC键清空input的效果。但是这样写不太好看,局限性太大,我们需要封装一下observable,把document.querySelector('#name')和'keydown'事件都换成参数

    function encapsulation(target: HTMLInputElement, eventName: string) {
      return new Observable((observer) => {
        console.log(observer.next)
        function handler(e) {
          observer.next(e);
        }
        target.addEventListener(eventName, handler);
        return () => {
          target.removeEventListener(eventName, handler);
        }
      });
    }

这样就哪个元素想设置为target就设置哪个元素,想绑定哪个事件就绑定哪个事件。我用的函数名是encapsulation,这样多好理解。原教程用的是formEvent,我至今不知道是什么意思。

 

还有一些至今未懂的语言,比如

使用 Observable 构造函数可以创建任何类型的可观察流。 当执行可观察对象的 subscribe() 方法时,这个构造函数就会把它接收到的参数作为订阅函数来运行。 订阅函数会接收一个 Observer 对象,并把值发布给观察者的 next() 方法。

 当执行可观察对象的 subscribe() 方法时,这个构造函数就会把它接收到的参数作为订阅函数来运行。英文文档The constructor takes as its argument the subscriber function to run when the observable’s subscribe() method executes. 我没搞清这句话的语法,就百度翻译了一下,"构造函数将要运行的subscriber函数作为其参数",和上面的正好相反。

最后,我大胆猜测:订阅者subscriber就是观察者observer。console.log发现observer的构造函数就是就是Subscriber。官网上一会儿subscriber一会儿observer的,统统视作observer

你可能感兴趣的:(Angular文档 Observable&Rxjs 部分解读)