RxJS - Observables, observers 和 operators 简介
RxJS 是响应式编程 (reactive programming) 强大的工具,今天我们将深入介绍 Observables 和 Observers 的内容,以及介绍如何创建自己的操作符 (operators)。 如果你之前已经使用过 RxJS,并希望了解 Observable 及 Operators (操作符) 的内部工作原理,那么这篇文章非常适合你。 什么是 ObservableObservable 就是一个拥有以下特性的函数:
在我们实现的示例中,我们将定义一个简单的 一个 Observable 对象设置观察者 (observer),并将它与生产者关联起来。该生产者可能是 DOM 元素产生的 为了更好地理解 Observable,我们来自定义 Observable。首先,我们先来看一个订阅的例子: const node = document.querySelector('input[type=text]'); const input$ = Rx.Observable.fromEvent(node,'input'); input$.subscribe({ next: (event) => console.log(`You just typed ${event.target.value}!`),error: (err) => console.log(`Oops... ${err}`),complete: () => console.log(`Complete!`) }); 该示例中, 什么是 ObserverObserver (观察者) 非常简单,在上面的示例中,观察者是一个普通的对象,该对象会作为 当 Observable 对象产生新值的时候,我们可以通过调用
此外在执行最终的 什么是 Operator正如上面所说的,Observable 对象能够执行链式操作,具体如下所示: const input$ = Rx.Observable.fromEvent(node,'input') .map(event => event.target.value) .filter(value => value.length >= 2) .subscribe(value => { // use the `value` }); 上面代码的执行流程如下:
简而言之,Operator 就是一个函数,它接收一个 Observable 对象,然后返回一个新的 Observable 对象。当我们订阅新返回的 Observable 对象时,它内部会自动订阅前一个 Observable 对象。 自定义 ObservableObservable 构造函数function Observable(subscribe) { this.subscribe = subscribe; } 每个 Observer 示例在我们深入介绍前,我们先来看一个简单的示例。之前我们已经创建完 const one$ = new Observable((observer) => { observer.next(1); observer.complete(); }); one$.subscribe({ next: (value) => console.log(value) // 1 }); 即我们订阅我们创建的 Observable 实例,然后通过 Observable.fromEvent下面就是我们需要的基础结构,即在 Observable 对象上需要新增一个静态方法 Observable.fromEvent = (element,name) => { }; 接下来我们将参考 RxJS 为我们提供的方法来实现自定义的 const node = document.querySelector('input'); const input$ = Observable.fromEvent(node,'input'); 按照上面的使用方式,我们的 Observable.fromEvent = (element,name) => { return new Observable((observer) => { }); }; 接下来我们来实现事件监听功能: Observable.fromEvent = (element,name) => { return new Observable((observer) => { element.addEventListener(name,(event) => {},false); }); }; 那么我们的
当我们调用 很好,那接下来我们要做什么?之前版本我们只是设置了监听,但没有调用 observer 对象的 Observable.fromEvent = (element,(event) => { observer.next(event); },false); }); }; 如你所知,当销毁 Observables 对象时,需要调用一个函数用来执行清理操作。针对目前的场景,在销毁时我们需要移除事件监听: Observable.fromEvent = (element,name) => { return new Observable((observer) => { const callback = (event) => observer.next(event); element.addEventListener(name,callback,false); return () => element.removeEventListener(name,false); }); }; 我们没有调用 现在让我们来验证一下最终实现的功能: const node = document.querySelector('input'); const p = document.querySelector('p'); function Observable(subscribe) { this.subscribe = subscribe; } Observable.fromEvent = (element,false); }); }; const input$ = Observable.fromEvent(node,'input'); const unsubscribe = input$.subscribe({ next: (event) => { p.innerHTML = event.target.value; } }); // automatically unsub after 5s setTimeout(unsubscribe,5000); 自定义操作符创建我们自己的操作符应该会更容易一些,现在我们了解 Observable.prototype.map = function (mapFn) { }; 该方法的功能与 JavaScript 中的 const input$ = Observable.fromEvent(node,'input') .map(event => event.target.value); 所以我们需要应用回调函数并调用它,这用于获取我们所需要的数据。在我们这样做之前,我们需要流中的最新值。这里是巧妙的部分,在 Observable.prototype.map = function (mapFn) { const input = this; }; 接下来我们在返回的 Observable 对象中执行 Observable.prototype.map = function(mapFn) { const input = this; return new Observable((observer) => { return input.subscribe(); }); };
最后我们来完善一下 Observable.prototype.map = function (mapFn) { const input = this; return new Observable((observer) => { return input.subscribe({ next: (value) => observer.next(mapFn(value)),error: (err) => observer.error(err),complete: () => observer.complete() }); }); }; 现在我们已经可以执行链式操作了: const input$ = Observable.fromEvent(node,'input') .map(event => event.target.value); input$.subscribe({ next: (value) => { p.innerHTML = value; } }); 我有话说Observable 与 Promise 有什么区别?Observable(可观察对象)是基于推送(Push)运行时执行(lazy)的多值集合。
什么是 SafeObserver ?上面的示例中,我们使用一个包含了 next、error、complete 方法的普通 JavaScript 对象来定义观察者。一个普通的 JavaScript 对象只是一个开始,在 RxJS 5 里面,为开发者提供了一些保障机制,来保证一个更安全的观察者。以下是一些比较重要的原则:
为了完成上述目标,我们得把传入的匿名 若想进一步了解详细信息,请参考 Observable详解 文章中 "自定义 Observable" 章节的内容。 参考资源
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |