【转载升级V7】 30 天精通 RxJS (05): 建立 Observable(一)

75 阅读5分钟

本文核心内容转载自blog.jerry-hong.com/series/rxjs… 源代码用的Rxjs v5, 为了本人自己学习,参考官网改为v7版本

整个RxJS 说白了就是一个核心三个重点

一个核心是Observable 再加上相关的Operators(map, filter...),这个部分是最重要的,其他三个重点本质上也是围绕着这个核心在转。

另外三个重点分别是

  • Observer
  • Subject
  • Schedulers

Observer 是这三个当中一定会用到却是最简单的,所以我们今天就会把它介绍完。Subject 一般应用到的频率就相对低很多,但如果想要看懂RxJS 相关的Library 或Framework,Subject 就是一定要会的重点,所以这个部分我们大概会花3-5 天的时间讲解。至于Schedulers 则是要解决RxJS 衍伸出的最后一道问题,这个部份会视情况加入或是在30 天后补完。

redux-observable就是用了Subject 实作的

让我卖个关子,先不说RxJS 最后一道问题是什么。

说了这么多,我们赶快进入到今天的主题Observable 吧!

建立Observable:new Observable

建立Observable 的方法有非常多种,其中new是一种方法。new Observable方法需要传入一个callback,这个callback会接收一个observer 参数,如下

 const observable = new Observable((subscriber)=>{
     subscriber.next(1);
 });

这个 callback 会定义 observable 将会如何发送值。

尽管 Observable 是基础,但 RxJS 的操作符是最有用的。操作符是能让你以声明方式轻松组合复杂异步代码的基本构造块。

我们可以订阅这个observable,来接收他送出的值,代码如下

const observable = new Observable((subscriber)=>{
     subscriber.next('Jerry');
     subscriber.next('Anna');
});

observable.subscribe({
    next(x) {
        console.log(x)
    }
})

当我们订阅这个observable,他就会依序打印出'Jerry' 'Anna'两个字串。

订阅Observable 跟addEventListener 在实作上其实有非常大的不同。虽然在行为上很像,但实际上Observable 根本没有管理一个订阅的清单,这个部份的细节我们留到最后说明!

这里有一个重点,很多人认为RxJS 是在做非同步处理,所以所有行为都是非同步的。但其实这个观念是错的,RxJS 确实主要在处理非同步行为没错,但也同时能处理同步行为,像是上面的程式码就是同步执行的。

证明如下

const observable = new Observable((subscriber)=>{
     subscriber.next('Jerry');
     subscriber.next('Anna');
});
console.log('start');
observable.subscribe({
    next(x) {
        console.log(x)
    }
});
console.log('end');

上面这段程式码会印出

start
Jerry
Anna
end

而不是

start
end
Jerry
Anna

所以很明显的这段代码是同步执行的,当然我们可以拿它来处理非同步的行为!

const observable = new Observable((subscriber)=>{
     subscriber.next('Jerry');
     subscriber.next('Anna');
     setTimeout(()=>{
         subscriber.next('RxJS 30 Days!');
     },30)
});
console.log('start');
observable.subscribe({
    next(x) {
        console.log(x)
    }
});
console.log('end');

这时就会印出

start
Jerry
Anna
end
RxJS 30 Days!

从上述的代码能看得出来

Observable 同时可以处理同步与非同步的行为!

观察者Observer

Observable 可以被订阅(subscribe),或说可以被观察,而订阅Observable 的对象又称为观察者(Observer) 。观察者是一个具有三个方法(method)的对象,每当 Observable 发生事件时,便会呼叫观察者相对应的方法。

观察者的三个方法(method):

  • next:每当Observable 发送出新的值,next 方法就会被呼叫。
  • complete:在Observable 没有其他的资料可以取得时,complete 方法就会被呼叫,在complete 被呼叫之后,next 方法就不会再起作用。
  • error:每当Observable 内发生错误时,error 方法就会被呼叫。

说了这么多,我们还是直接来建立一个观察者吧!

const observable = new Observable((subscriber)=>{
     subscriber.next('Jerry');
     subscriber.next('Anna');
     subscriber.complete();
     subscriber.next('not work');
});
const observer = {
  next: (x) => console.log(x),
  error: (err) => console.error(err),
  complete: () => console.log('complete'),
};
observable.subscribe(observer);

上面这段程式码会印出

Jerry Anna complete

上面的范例可以看得出来在complete 执行后,next 就会自动失效,所以没有印出not work

下面则是送出错误的范例

const observable = new Observable((subscriber)=>{
    try {
        subscriber.next('Jerry');
        subscriber.next('Anna');
        throw 'some exception';
    } catch(err) {
        subscriber.error(err);
    }
});
const observer = {
  next: (x) => console.log(x),
  error: (err) => console.error('Error: ',err),
  complete: () => console.log('complete'),
};

observable.subscribe(observer);

这里就会执行error 的function 印出Error: some exception

另外观察者可以是不完整的,他可以只具有一个next 方法,如下

const observer = {
  next: (x) => console.log(x),
};

有时候Observable 会是一个无限的序列,例如click 事件,这时complete方法就有可能永远不会被呼叫!

我们也可以直接把next, error, complete 三个function 依序传入observable.subscribe,如下:

observable.subscribe(
    value => { console.log(value); },
    error => { console.log('Error: ', error); },
    () => { console.log('complete') }
)

observable.subscribe会在内部自动组成observer 对象来操作。

细节

订阅Observable 的行为比较像是执行一个对象的方法,并把资料传进这个方法中。

我们以下面的程式码做说明

const observable = new Observable((subscriber)=>{
    try {
        subscriber.next('Jerry');
        subscriber.next('Anna');
        throw 'some exception';
    } catch(err) {
        subscriber.error(err);
    }
});
observable.subscribe({
  next: (x) => console.log(x),
  error: (err) => console.error('Error: ',err),
  complete: () => console.log('complete'),
});

像上面这段程式,他的行为比较像这样

function subscribe(subscriber) {
    subscriber.next('Jerry');
    subscriber.next('Anna');
}
subscribe({
    next: (x) => console.log(x),
    error: (err) => console.error('Error: ',err),
    complete: () => console.log('complete'),
});

这里可以看到subscribe 是一个function,这个function 执行时会传入观察者,而我们在这个function 内部去执行观察者的方法。

订阅一个Observable 就像是执行一个function

今日小结

今天在讲关于建立Observable 的实例,用到了create的方法,但大部分的内容还是在讲Observable 几个重要的观念,如下

  • Observable 可以同时处理同步非同步行为
  • Observer 是一个对象,这个对象具有三个方法,分别是next , error , complete
  • 订阅一个Observable 就像在执行一个function