Angular 简介
Angular 由 google 创建,于 2010 年正式发布,到目前已经更新到 v8.0 版本。相比于目前炙手可热的 React 与 Vue 框架来说,Angular 自带完备的生态系统使其更能被称之为一款 “ 框架 ”.
Angular 对 typescript 的完美支持(angular 本身就是由 typescript 去编写的)以及它对模块化和层次依赖注入的架构方式,使其在构建微服务前端系统也有一定优势. 此外 Angular 框架中引入 Rxjs(ReactiveX javascript) , 运用 Observable 去解决异步问题,使异步问题变的更加简单和可控。
Observable (可观察对象)
社区对于 Observables, Observable, Observer, Subject, Subscription 等有很多介绍,概念性的知识点很难记忆,我概述了几条,并记录顺便分享一下自己对这些概念的理解:
(1) Observables是Rx的核心, Rx 是(Reactive Extensions)的简写,而 rxjs 则是 Observable 在 Javascript 版本的实现,除了 Rxjs, 还有 RxJava, RxDart, RxSwift 等语言的实现版本。
(2) Rxjs 依据 Observable 作为核心,对可观察对象 Observable 进行赋能,将其转换为操作流,通过 operators 操作符完成对数据流的变换、组合、操纵等。
(3) Observable 是一种新的 push 体系(Pull 和 Push 是两种不同的协议,用于描数据的生产者 和 数据消费者之间的联系方式)。可以通过以下例子简单加以理解:
function GetName()
{
const name: string = 'i come from a method';
return name;
}
const consumerName: string = GetName(); // consumerName 'i come from a method'
JS 通过调用函数或取数据,此时函数是数据的产生者。函数必须被 call 即调用才可以被触发,这就是一种 pull(拉取) 体系。
那么在 Rxjs 中:
import { Observable } from 'rxjs';
const NameObservables$: Observable<string> = new Observable(
subscriber => {
const name: string = 'i come from a method';
subscriber.next(name);
}
);
NameObservables$.subscribe((name: string) => {
console.log(name); // 'i come from a method'
});
代码中,我们通过 subscribe 来获取数据,这和直接调用函数有什么区别呢?
观察代码我们可以发现,我们将函数和消费者之前进行了解耦,我们只是订阅了数据生产者返回的NameObservables$这个可观察对象,这使得我们在获取原数据的操作上多了一层隔离,利用这层隔离,我们可以做很多事,比如利用各种operators对原数据进行各类操作, 并且我们对一类数据源进行了一定程度的复用,因为任何需要 name 的地方都可以订阅这个 Observable。
Observable 区别于普通函数的另一个特点就是,Observable 可以异步返回多个值,并且由于上面提到的隔离,我们可以针对不同的场景分别去处理这些值,只要订阅 Observable 对象的订阅者们,都可以获取到这些数据。大概像这样:
import { Observable } from 'rxjs';
const NameObservables$: Observable<string> = new Observable(
subscriber => {
const name: string = 'i come from a method';
subscriber.next(name);
const info: any = 'i am happy';
subscriber.next(info);
setTimeout(() => {
const info2: any = 'i like rxjs';
subscriber.next(info2);
}, 2000)
}
);
NameObservables$.subscribe((name: string) => {
console.log(name); // 'i come from a method'
console.log(name); // 'i am happy'
console.log(name); // delay 2s => 'i like rxjs'
});
(4) 可观察对象 Observable 本质也是基于 订阅者模式 的一种应用,一个 Observable 构造函数可以创建任意类型的观察流供观察者(Observer)进行订阅操作。(订阅?:也就是获取数据,可以简单理解为订阅微信公众号)。生活中我们通过关注一个公众号获取订阅通知,在 Observable 的世界里,则通过 订阅(subscribe)操作去获取可观察对象流转出来的信息。这个过程中代码简单模拟一下如下:
class Observable {
constructor(subscribe){
this.subscriptions = [];
this._subscribe = subscribe;
}
subscribe(observer){
const _this = this;
this.subscriptions.push(observer);
this._subscribe.call(this, observer);
return {
unsubscribe: () => {
const subscriptionIndex = _this.subscriptions.indexOf(observer);
_this.subscriptions.splice(subscriptionIndex, 1);
}
}
}
}
let testObservable$ = new Observable(function(observer){
observer.next(1);
observer.next(2);
observer.next(3);
observer.complete();
});
const subscription = testObservable$.subscribe({
next:function(val){ console.log('next', val); },
error:function(error){ console.log('error', error); },
complete:function(){ console.log('complete'); }
});
// 取消订阅,不再接受消息
setTimeout(() => {
subscription.unsubscribe();
}, 2000);
(5) 通过上面的代码也可以发现,一个Observer(观察者) 能获取到 3 种通知,即 next, error, complete. 当有人订阅Observable的实例时,需要通过调用 subscribe 方法来获取到一个 observer对象,subscribe 方法会返回一个 subscription 对象,调用 subscirption 的 unsubscribe 方法, 订阅者 Observer 就会停止接收通知。原有的Observable对象依然存在。
(6) 结合上面了解到的 Observable 特性,我们可以对比 Promise体系。熟悉 Promise 的朋友都知道 ,Promise 的 executor 函数接受 resolve, reject 方法,通过调用 resolve 或者 reject 来触发回调数组,将 resolve 的 data 或者是 reject 的 data 通过回调,返回给 then 方法中的 onFulfilled 函数。Promise 单个体系中,因为这些 value 被回调回去的时间是非常确定的,所以 promise 也是一种 push 体系, promise 一旦被 resolve 之后便无法再次返回和取消了,至少他本身不具备取消的能力。下面是 promise 部分简单的实现:
class Promise {
constructor(executor) {
this.status = PENDING;
this.value = void 0;
this.err = void 0;
this.fulfilledList = new Array(); // fulfilled sub lists
this.rejectedList = new Array(); // rejected sub lists
let resolve = (value) => {
if (this.status === PENDING) {
...
this.fulfilledList.forEach(cb => cb());
}
}
let reject = (err) => {
if (this.status === PENDING) {
...
this.rejectedList.forEach(cb => cb());
}
}
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onFulfilled, onRejected) {
let promiseThen = void 0;
promiseThen = new Promise((resolveNext, rejectNext) => {
....
if (this.status === PENDING) {
this.fulfilledList.push(() => {
...
let result = onFulfilled(this.value);
...
});
this.rejectedList.push(() => {
...
let result = onRejected(this.err);
...
});
}
});
return promiseThen;
}
}
了解 Observable 的诸多概念之后,我总结了以下几点:
(1) Observable 是一种新的 push 体系, 它通过把异步操作封装成一个可以自由组合,灵活变化的可观察对象,来对异步数据流进行控制,是一种高级的 promise。
(2) Observable 是 Rxjs 的核心,真正强大的是 Observable 这种观察和订阅模式配合 Rxjs 各类操作符实现对异步流的灵活控制 。
(3) Observable 对比 Promise 拥有可取消,多复用,多值返回, 异步可控等优点。
(4) Observable 数据源可以保留,并可以被多个观察者使用的特性,使得跨组件的通讯变更加简单。
了解了 Observable 的概念及简单原理,我们可以更好的在实际业务场景去使用 Observable 和 Rxjs 。
感谢您的阅读~