若是对 RxJS 的 operators (操做符) 不熟悉的话,建议读者在阅读本文时,先阅读 RxJS - Observables, observers 和 operators 简介 这篇文章。javascript
Operator 是一个函数,它接收一个 Observable 对象,而后返回一个新的 Observable 对象。当咱们订阅新返回的 Observable 对象时,它内部会自动订阅前一个 Observable 对象。java
比较常见的有如下三种方式:git
1.使用 ES7 函数绑定运算符 ::
(可以使用 BabelJS 进行转换)github
someObservable::mySimpleOperator(x => x + '!');
2.继承 Observable 类,并重写 lift()
方法typescript
class MyObservable extends Observable { lift(operator) { const observable = new MyObservable(); //<-- important part here observable.source = this; observable.operator = operator; return observable; } // put it here .. or .. customOperator() { /* do things and return an Observable */ } } // ... put it here... MyObservable.prototype.mySimpleOperator = mySimpleOperator;
3.直接添加到 Observable.prototype
对象上json
Observable.prototype.mySimpleOperator = mySimpleOperator; someObservable.mySimpleOperator(x => x + '!');
当咱们使用 Angular HTTP 服务时,咱们须要调用 Response 对象的 json()
方法把服务端接口返回的数据,转换为 JSON 对象,例如:bootstrap
this.http.get('https://api.github.com/orgs/angular/members?page=1&per_page=5') .map(res => res.json());
对于每一个接口,咱们都须要调用 map 操做符对返回的数据作对应的处理。那能不能简化这个操做呢?答案是有的,咱们能够经过自定义一个 toJSON 操做符来简化上述的过程。具体实现以下:segmentfault
function toJSON<T>(): Observable<T> { return this.map(( response : Response ) => response.json()); }
上面代码中,this
指向源 Observable 对象,即调用 http 对象的 get()
方法后返回的 Observable 对象。此外咱们直接返回了调用 map()
操做符后新建的 Observable 对象。api
为了可以使用咱们自定义的 toJSON
操做符,咱们须要把它添加到 Observable 的原型对象上:babel
Observable.prototype.toJSON = toJSON;
最后的一件事是咱们须要添加如下的定义:
declare module "rxjs/Observable" { interface Observable<T> { toJSON : typeof toJSON; } }
import { Observable } from 'rxjs/Observable'; function toJSON<T>(): Observable<T> { return this.map(( response : Response ) => response.json()); } Observable.prototype.toJSON = toJSON;
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { HttpModule } from "@angular/http"; import { AppComponent } from './app.component'; import './custom-operators'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, HttpModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
import { Observable } from 'rxjs/Observable'; import { Component, OnInit } from '@angular/core'; import { Http } from '@angular/http'; import 'rxjs/add/operator/map'; interface Member { id: string; login: string; avatar_url: string; } @Component({ selector: 'app-root', template: ` <h3>Angular Orgs Members</h3> <ul *ngIf="members"> <li *ngFor="let member of members;"> <p> <img [src]="member.avatar_url" width="48" height="48"/> ID:<span>{{member.id}}</span> Name: <span>{{member.login}}</span> </p> </li> </ul> ` }) export class AppComponent implements OnInit { members: Member[]; constructor(private http: Http) { } ngOnInit() { this.http.get(`https://api.github.com/orgs/angular/members?page=1&per_page=5`) .toJSON<Member[]>() // 使用自定义 toJSON 操做符 .subscribe(data => { if (data) this.members = data; }); } }
// src/typings.d.ts (在该文件下,新增如下内容) export declare function toJSON<T>(): Observable<T>; declare module "rxjs/Observable" { interface Observable<T> { toJSON : typeof toJSON; } }