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 。
感謝您的閱讀~