angular2 学习笔记 ( rxjs 流 )

更新 : 2019-06-2

defer 用于延后一个 function 执行. 当 subscribe 后才被执行, 通常用于做 promise retry 

比如我有一个 promise 方法

async function getValueAsync(ok: boolean): Promise<string> {
    return new Promise((resolve, reject) => {
        console.log('run');
        setTimeout(() => {
            if (ok) {
                resolve('dada');
            }
            else {
                reject('fail');
            }
        }, 3000);
    });
}
from(getValueAsync(false)).pipe(
    retry(1)
).subscribe({
    next: (value) => { console.log(value); },
    error: (err) => { console.log('Error: ' + err); },
    complete: () => { console.log('complete'); }
});

如果我直接这样跑是不能 retry 的. refer : https://stackoverflow.com/questions/33072512/rx-frompromise-and-retry 这里有解释 

用 defer

defer(() =>  getValueAsync(false)).pipe(
    retry(2)
).subscribe({
    next: (value) => { console.log(value); },
    error: (err) => { console.log('Error: ' + err); },
    complete: () => { console.log('complete'); }
});

这样就可以了

 

 

 

更新 : 2018-03-12 

学 rxjs 最好的就是看官网的文档,解释的很清楚. 

http://cn.rx.js.org/manual/overview.html#h39

https://rxjs-cn.github.io/learn-rxjs-operators/

function subscribe(observer) {
  var intervalID = setInterval(() => {
    observer.next('hi');
  }, 1000);

  return function unsubscribe() {
    clearInterval(intervalID);
  };
}
var unsubscribe = subscribe({next: (x) => console.log(x)});
var unsubscribe = subscribe({next: (x) => console.log(x)});
// 稍后:
unsubscribe(); // 清理资源

上面这一段代码让我明白了几个重点

1. 惰性 (当 observable 被创建时,没有 subscribe 是不会开始运行的, 因为 observable 就像函数调用 )

2. 每一个 subscribe 是独立的 

3. observable 和常用的 addEventListener 不同,它不会吧所有的 observer 保存在列表里头. 

 

而 subject 则是道道地地的 addEventListener, 它会保存所有 observer 在列表里. 

而把它们结合的方式就是 observable.subscribe(subject); 

因为 subject 就是一个 observer 拥有 next 方法. 

这就是 rxjs 其中 2 大核心, observable and subject 

至于其它的 subject 还有一堆的 operator, create observable 等,都是基于这 2 个核心的扩展而已. 

 

 

更新 : 2017-11-14 

最近从新看了 30 天 rxjs, 这里补上一些笔记.

顺便提一下, ng 5.x 开始 rxjs 的写法换掉了 

参考 : https://github.com/ReactiveX/rxjs/blob/master/doc/lettable-operators.md

import { combineLatest } from 'rxjs/observable/combineLatest';
import { catchError, take } from 'rxjs/operators';

combineLatest(pendingEmitters).pipe(
    take(1),
    catchError(() => {
        reject();
        return '';
    })
).subscribe(() => {
    resolve();
});

不像 jquery 那样串连了. 

 

1.concat 

https://ithelp.ithome.com.tw/articles/10187520

concat 是把多个 observeable 合并起来, 其特色是只有前面一个 observeable complete 了后边的 observeable 才开始起作用.

concat(o1,o2,o3), o1 没有 complete 的话, o2 怎么叫都不会触发.

另一个说法就是 concat 先 subcribe o1, 然后等到 o1 completed 后再去 subscribe o2, 一直到完, 那它自己也就 completed 了.

concat 是可以调用的 import { concat } from 'rxjs/observable/concat';

 

2. merge

https://ithelp.ithome.com.tw/articles/10187520

它和 concat 都是用来合并的. 区别是它不需要等 complete, 任何一个 observable 触发都会有效果. 

换句话说就是 merge 会直接 subcribe 所有的 obserable 不像 concat 那样会等 completed.

merge(o1,o2) o1 没有 complete, o2 叫一样有效.

 

3.concatAll

concatAll 属于 operators 

o1.pipe(map(_ => o2),concatAll()) 

每一次 o1 叫,都会产生多一个 o2 

比如 o1 叫了 3 次 , 那么就有 3 个 o2 

concatAll 就是把这 3 个组合起来( 每一次 o1 叫, 都会 push 新的 o2 去这个 array ) 然后 concat(o2,o2,o2),后续的步骤就和 concat 一摸一样了. 所以它起到了打平和 concat 的作用.

 

4. mergeAll

mergeAll 和 concat 是同一个原理只是, 最后不是用 concat 而是用 merge(o2,o2,o2);

另外, mergeAll(2) 可以传入一个变量去控制允许并发的数量 

比如你输入 2,  那么 a 叫了 3次, 你有 merge(o2,o2,o2), 第3个 o2 叫的时候本来是会有效果的,但是由于限制了 2, 那么只能等第一或第二个 o2 complete, 第 3 o2 叫才有效果了。确保同一时期只有 2 个.

note mergeAll(1) === concatAll()

 

5.switchAll

没有 switch 只有 switchAll 

它和 concatAll, mergeAll 的区别是, o1 每一次叫, 永远只保留最新的 o2, 之前的 o2 统统丢掉. 

 

concatAll, switchAll, mergeAll 

https://ithelp.ithome.com.tw/articles/10188325

这 3 个都是用来打平 obs 

concatAll 上面讲了重点是会等上一个 complete 才去下一个 

switchAll 则是一旦有新的一个来,旧的就忽略掉. 

mergeAll 则是并发处理.

 

6 concatMap, switchMap, mergeMap 

https://ithelp.ithome.com.tw/articles/10188387

就是 map() + switchAll(), map() + concatAll(), map() + mergeAll() 的缩写而已. 

还有个好处是它可以传入一个方法 (a,b,c,d) => next, 可以获取到 o1,o2 的值然后返回下一个值. 

 

6.5 exhaustMap 

这个和 concatMap 很像. 唯一的区别是, concat 等待第一个 complete 了以后会去 subscribe 下一个(第二个)

而 exhasust 呢, 它会去 subscribe 下下下下一个 (最后一个), 

 

7. combineLatest 

https://ithelp.ithome.com.tw/articles/10187638

它也是用来做合拼处理的,

它需要等 "每一个" observable 至少有一个开始值之后才开始工作. 这和 merge 不同, merge 不需要等

它每一次触发都可以获取到所有 observable 当前的值, 这和 merge 不同, merge 每一次触发只能获取一个 observable 的值.

 

8.withLatestFrom

https://ithelp.ithome.com.tw/articles/10187638

它和 combineLatest 一样,唯一的区别是, 它只有 main observable next 值时才会触发 callback , 其它 observable next 只是记入值而已. 

 2019-06-14 补上一个例子, form value update 但是只有 button click 的时候才 emit

this.formGroup = this.formBuilder.group({
  date: [null, Validators.required]
});

const f = this.formBuilder.group({
  name: [''],
  age: [11]
});
const button = new Subject();

button.pipe(withLatestFrom(f.valueChanges)).subscribe(v => {
  console.log(v);
});


f.setValue({ name: 'dada', age: 15 });
f.setValue({ name: 'dada', age: 18 });
button.next('dada');
button.next('dada2');

 

 

9. zip 

https://ithelp.ithome.com.tw/articles/10187638

它也是合并. 

它的关键是顺位, 比如 2 个 observables, 2 个都 next 1次 的时候就会 callback 并得到 2 个的第一个值, 如果 2 个不平均, 比如一个 next 了 10 次, 另一个 next 2 次, 那么 callback 就只有 2 次. 

等第 2 个 next 第 3 次时, callback 就会得到 第1和第2个的第3次 next 的值. 

 

10. scan 

https://ithelp.ithome.com.tw/articles/10187882

就是 js 的 reduce, 区别在于它总是返回 observable. 每一次 next 触发, callback 都可以获取上一次的值 + 现在的值做一些处理, 返回下一个值. 

 

11. buffer 

https://ithelp.ithome.com.tw/articles/10187882

buffer, bufferTime, bufferCount 

它用于累积 next 等待另一个 obserable next 的时候才触发 callback 

o1.pipe(buffer(o2))...   o2 next 的时候 o1 的 callback 才触发, 并且返回期间所有的 o1 next 值. 

 

12. delay & delayWhen

https://ithelp.ithome.com.tw/articles/10187999

delay(1000) 就是延迟 1 秒咯, 如果我们要每一次都不用的话. 

就用 delayWhen(v => empty().delay(v + 1000)); 必须返回一个 observable

 

13.debounce & debounceTime 

https://ithelp.ithome.com.tw/articles/10188121

它和 buffer 有点像, 都是会累积值, 但是区别在于, 当一个新值被 next 进来, 它会把之前的值释放掉, 并且时间从新开始算. 

 

14. throttle & throttleTime

https://ithelp.ithome.com.tw/articles/10188121

它用于限制一个时间内, 最高触发的频率. 比如 throttleTime(1000) 就限制了一秒内不管 next 几次, 只有第一次会 callback 往后的都不会, 直到下一秒开始. 

 

15.distinct, distinctUntilChanged

https://ithelp.ithome.com.tw/articles/10188194

它就是我们熟悉的 distinct, 如果值相同就忽略 callback 

distinct((x) => { return x.value }); 可以提供一个取值的方法,对比估计是用 === 

distinct 会把所有的值都存起来做对比, distinctUntilChanged 的区别是它只会存最后一次的值做对比.

 

16.catchError, retry, retryWhen, repeat

https://ithelp.ithome.com.tw/articles/10188263

catchError 是捕获错误, 

catchError((error, obs) => obs); 返回第 2 个参数 obs 可以实现从跑. 

retry 就是做了上述的事情, 而 retry 多了一个可以指定次数, retry(3) 从试 3 次 

retryWhen(errorObs => errorObs.delay(1000)) retryWhen 可以让我们操作更多,比如间隔多久才 retry 下一次等等. 

repeat 和 retry 是一样的,区别在于 retry 必须在 error 时才会有, 而 repeat 则是不管有没有 error 都会执行. 

 

 

17.  ReplaySubject, BehaviorSubject

behavior 代表一个保持值的 subject, 一旦订阅马上会触发 callback 并获取到最新的值. 即便不订阅也可以调用 .value 来获取当前值.

replay 会缓存之前的 next 一旦新的订阅加入,就会 playback 之前所有的 next 值. 

 

  

rxjs 在处理 dom 事件时是非常好用的. 

步骤一般上是 获取所有 element, 建立所有的 event 

然后就是各做 rxjs operator 对 event 和 element 的处理. 

参考 : https://ithelp.ithome.com.tw/articles/10187756

 

 

 

 

  

更新 : 2017-10-14 

import 'rxjs/add/observable/combineLatest'; //每一个至少一次后才开始触发(无需 completed), 一个一次可以获取大家最新的 value
import 'rxjs/add/observable/forkJoin'; // 类似 promise.all 所有 observable 需要 最少next 一次 and completed 才会触发,所以只触发一次获取所有 value
import 'rxjs/add/observable/merge'; // 用来监听多个 click event 一个一次, merge(a,b) 如果 a,b 都有初始值, 那么会马上触发 2 次.
import 'rxjs/add/observable/concat'; // 和 merge 一样, 唯一不同的是它需要第一个 completed 才会触发第 2 个, 第一还没 completed 第 2 next 都不会叫哦

 

更新 2017-05-17 

今天被 toPromise 给骗了. 

我一直以为, 所有的 "流" 都可以轻松的转成 await stream.toPromise();

后来我发现有个流一直没有反应 

let subject = new BehaviorSubject('a');
let o = subject.asObservable();
o.toPromise().then(() => console.log('pro')); //不会跑
setTimeout(()=> {
  subject.next('haha');
  //subject.complete();
}, 1000);

上网找了一下才发现,原来 toPromise().then 必须是 completed 才会跑

所以上面的 subject.complete() 必须要打开才行. 这也意味着 toPromise 只能用在一次的 async 中, 如果是要持续 subscribe 的情况下请使用 .subscribe() 

 

 

 

更新 2017-04-02 

Subject 的主要功能就是观察者模式. 

我们可以随时写入值,完全自己操控. 

但是有时候我们希望它依赖于其它 stream 那么我们使用 connect 

let s1 = new Subject();
let o1 = s1.asObservable(); //我们想以来的 stream 

let s2 = new Subject();
s2.subscribe(v => console.log(v));

o1.subscribe(v => s2.next(v),v => s2.error(v)); //第1种写法,超麻烦
o1.subscribe(s2); //第2种,可是我没有要马上 subscribe 的话呢 ?  
let connector = o1.multicast(s2); //第3种
connector.connect();

s1.next("value");

 

 

更新 2017-03-31

好文,力推 : http://ithelp.ithome.com.tw/articles/10189028?sc=iThomeR
再谈谈 cold & hot 

observeable 是 default cold 的. 

code 的意思是说, 当有多个 subscribe 时,每一个都是一条独立的链.

比如 http 多个 subscribe 的话,你会发现你的 request 会发了好几个.

hot 的意思则是每个 subscribe 共享一个链, 不管你什么之后插入subscribe 你都不会从新开始. 

把一个 cold 变成 hot 的方法是使用 Subject 充当中间人. 

具体看这 3 篇就明白了 

http://ithelp.ithome.com.tw/articles/10188633

http://ithelp.ithome.com.tw/articles/10188677

http://ithelp.ithome.com.tw/articles/10188750

这里介绍一下 ReplaySubject

Subject.subscirbe() , 不会马上执行, 因为要等待下一个 Subject.next

BehaviorSubject.subscribe() , 马上执行, 因为里面一定会有值. 

ReplaySubject.subscribe(), 不一定马上执行,如果曾经 .next 过才会执行 

multicast, refCount,publish,share 的目的就是把 cold 转换成 hot .

其原理就是使用了 Subject 系列. 

multicast 后来被 publish 取代了. publish 对应 subject 所以有 publishBehavior, pulishReplay 

refCount 是 connect 的意思,就是把 observer 链接上 subject 的动作. 

由于 publish().refCount() 太经常用到,所以发明了 share 写的更快了嘻嘻。

在使用 ng 的 http 时要注意. observable 是 cold 的。但很多情况下我们更希望它是 hot 的. 

每一次的 subscribe 应该只返回同一个结果, 而这个 http 只发一次请求. 

这时我们需要这样写 : http.get().publishReplay(1).refCount() 

publishReplay(1) 之后的每一个 subscribe 都会得到同一个资料了.

 

 

更新 : 2017-03-27 

什么时候需要 unsubscribe ? 

http 不需要, router param 也不需要. 

下面说说几个情况 

1. Subject.complete 之后, 所有的 subscribe 都不会再触发, 新的 subscribe 也加不进来了. 

所以如果我们知道订阅的 Subject 之后会被 complete 那么我们可以无需担心 unsubscribe 的问题 

2. 使用 async/await toPromise 可以避开 unsubscribe 的问题. 

3. 可以使用 .first(判断) 表示什么时候开始拿然后停 (比如一个值需要等待 ajax)

4. 使用 takeWhile(判断) 来决定什么时候取消订阅. 

5. 使用 OnDestroy 

 

 

更新 : 2017-03-18

Observable, 
Subject,
BehaviorSubject
的区别和用法 
 
当我们手中有一个 Observable, 我们可以去监听它,那么往后的事情发生我们都会知道。
但是, 之前发生的事情我们都没办法知道. 我们也没办法用它广播一个新的事件。
Observable 能做的事情, Subject 都可以做到. 而 Subject 多了一个能力,就是可以用它广播一个新事件出去. 
所以如果你站在一个监听者的角度, Subject 和 Observable 没啥区别. 你依然没办法知道过往发生的事情. 也只有在下一次事件广播时才会被通知. 
Subject 能做的事情 BehaviorSubject 都可以做,能监听也能广播. 最大的特点在于它能知道过往的事情。
当你手中有一个 BehaviorSubject 你可以马上调用 .value 获取当前的值, 你订阅它的话,你也会立马收到一个事件,而不像 Subject 或 Observable 一直傻傻等下一次广播才能得到值. 
 
自己选择用吧.
 
ng 的 http.get 返回的是 Observable, 你一监听它你会马上获得响应, 从这里我们就可以推断出沿着这条链往上走最终就是一个 BehaviorSubject. 因为只有 BehaviorSubject 被监听的时候才会马上得到响应。

 

2016-09-23

RxJS 博大精深,看了好几篇文章都没有明白. 

范围牵扯到了函数响应式开发去了... 我对函数式一知半解, 响应式更是第一次听到... 

唉...不过日子还是得过...混着过先呗

我目前所理解的很浅, 大致上是这样的概念.

1.某些场景下它比 promise 好用, 它善于过滤掉不关心的东西. 

2.它是观察者模式 + 迭代器模式组成的 

3.跟时间,事件, 变量有密切关系

4.世界上有一种东西叫 "流" stream, 一个流能表示了一段时间里,一样东西发生的变化. 

  比如有一个值, 它在某段时间里从 "我" 变成 "你" 再变成 "他". 

  而我们可以对这个流进行观察,所以只要它发生变化,我们就会发现然后做任何事情。

5.站在游览器的角度, 服务器推送数据过来, 用户操作界面, timer 都是我们关心的流.

好,来看例子. 

我们通过 new Subject 来创建流. 也可以使用 new EventEmitter 或者 BehaviorSubject. 这些都继承了 Subject

EventEmitter 是 ng2 提供的

BehaviorSubject 可以填入初始值

import { Subject } from "rxjs/Subject";
private textEmitter: Subject<string> = new Subject(); 

要改变流中的值,我们使用 .next(value), 这个是迭代器的概念咯

keyup(value : string)
{
    this.textEmitter.next(value);
}

那么订阅是这样的 

ngOnInit() {
    this.text$ = this.textEmitter
        .debounceTime(500)
        .distinctUntilChanged()
        .switchMap(v => this.getDataAsync(v));

    this.text$.subscribe((value) => {
        console.log(value);
    });            
}

input keyup 性能优化, 我们通常会写一个 timeout + cleartimeout 的方式, 这个 debounceTime 就是干这个的 

流更新结束后 500ms 才会通知观察者 

distinctUntilChanged 是说只有当值和上一次通知时的值不一样的时候才通知观察者 

.map 和 .switchMap 都是用来对值进行处理的, 这个和 array.map 概念是一样的

而 .map 和 .switchMap 的区别是 .swichMap 处理那些返回 Observeable 的值 

getDataAsync(value : string): Observable<string>
{        
    let subject = new Subject();
    setTimeout(() => {
        console.log("after 2second");
        subject.next(value + "final");
    }, 2000);
    return subject;
}

如果我们使用 map 的话,它会直接返回 "subject" 这个对象, 而如果用 switchMap 它会返回这个 subject 对象的响应值.

<input type="text" #input (keyup)="keyup(input.value)" />
<p>{{ text$ | async }}</p>

ng2 提供了一个 async Pipe, 它会监听左边这个 text$ stream. 后面加一个 $ 符号通常用来表明这是一个 stream.

还有一个常用的功能是 combineLatest

就是可以同时监听多个流,只要其中一个有变动,那么所有的最新值都会发布出去, 可以用来实现依赖属性.

这里需要注意一点 combineLatest 的所有流都必须有值, 不可以是一个从来都没有 next 过的 Observable 不然它就不会运行了.

最简单的方法是使用 observable.startWith(null) 让它有一个值. 

@Component({
    selector: "compute-property",
    template: ` 
        <input type="text" #input1 (keyup)="text1.next(input1.value)" />
        <input type="text" #input2 (keyup)="text2.next(input2.value)" />  
        {{ result$ | async }}                 
    `
})
export class ComputePropertyComponent implements OnInit {

    text1: BehaviorSubject<string> = new BehaviorSubject<string>("a");
    text2: BehaviorSubject<string> = new BehaviorSubject<string>("b");
    result$: Observable<string>;
    constructor() {}
    
    ngOnInit() {
        this.result$ = Observable.combineLatest(this.text1, this.text2).map(values => {          
            return values[0] + " " + values[1];
        }); 
    }     
}

还有 bufferCount, bufferTime 也是常用到

text: Subject<number> = new Subject<number>();
    
ngOnInit() {
    this.text.bufferCount(2)
        .subscribe(v => console.log(v)); //[v1,v2] 存够 count 了就发布

    this.text.bufferTime(2000)
        .subscribe(v => console.log(v)); //[v1,v2,...]把 2 秒内的所有 next value 放进来
}

Observable.of 可以简单的返回一个默认值 

Observable.of<string>("").subscribe(v => console.log(v));

rxjs 整个文档非常大,要按需加载.

通常做法是为项目开一个 rxjs-operators.ts 

import 'rxjs/add/observable/throw'; 
import 'rxjs/add/observable/combineLatest'; 
import 'rxjs/add/observable/from'; 
import 'rxjs/add/observable/of'; 
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/toPromise';
import 'rxjs/add/operator/startWith'; 
import 'rxjs/add/operator/bufferCount';
import 'rxjs/add/operator/bufferTime';

放入常用的方法 

然后再 app.module.ts 里面导入它 

import './rxjs-operators'; 

 

Hot or cold , share or not

refer : 

http://blog.thoughtram.io/angular/2016/06/16/cold-vs-hot-observables.html

http://blog.csdn.net/tianjun2012/article/details/51351823

1. by default, observable is not share.

let sub = new Subject();
let obs = sub.map(v => {
    console.log("ajax call"); 
});
obs.subscribe(v => console.log("subscribe 1"));
obs.subscribe(v => console.log("subscribe 2"));         
sub.next("value");

ajax 发了 2 次. angular2 的 Http 也是 not share 哦. 

所以当我们有多个 subscribe 的时候要想一想是否我们需要 share 

let obs = sub.map(v => {
    console.log("ajax call"); 
}).share();

调用一个 share 方法就可以了,或者是 

let obs = sub.map(v => {
    console.log("ajax call"); 
}).publish().refCount();

效果是一样的. 

 

by default, observable is cold.

意思是说只有在 subscribe 出现了以后才会启动. ( 当第一个 subscribe 出现时, observable 就会立刻启动了哦 ) 

let sub = new Subject();
let obs = sub.map(v => {
    console.log("ajax call");
});
sub.next("aaa");
//obs.subscribe(v => console.log("subscribe 1"));
//obs.subscribe(v => console.log("subscribe 2")); 

ajax 不会触发. 

如果我们希望它在没有 subscribe 的情况下触发的话, 可以这样写. 

let sub = new Subject();
let obs = sub.map(v => {
    console.log("ajax call");
}).publish();
obs.connect();
sub.next("aaa");

至于什么情况下使用哪一种,我还没有实战,以后再说.

多一个例子解释: 

let obs = Observable.create(observer => {
    console.log("observer run");
    observer.next(Date.now());
});
obs.subscribe(v => console.log("1st subscriber: " + v));
obs.subscribe(v => console.log("2nd subscriber: " + v));     
//observer run
//1st subscriber: 1474649902498
//observer run
//2nd subscriber: 1474649902501 

no share. 所以 observer run 了 2 次. 

let obs = Observable.create(observer => {
    console.log("observer run");
    observer.next(Date.now());
}).share();
obs.subscribe(v => console.log("1st subscriber: " + v));
obs.subscribe(v => console.log("2nd subscriber: " + v));     
//observer run
//1st subscriber: 1474650049833

share 了, 所以 observer only run 1 次.

cold, 所以当第一个 subcribe 出现后 observer 立刻运行 -> .next 更新了 value -> 第一个 subcribe callback 被调用 -> 整个过程结束 -> 然后第2个 subcribe 注册 .. 由于是 share 所以 observer 没有载被触发. 第2个 subscribe callback 没有被调用. 

延后触发的做法 : 

let obs = Observable.create(observer => {
    console.log("observer run");
    observer.next(Date.now());
}).publish();
obs.subscribe(v => console.log("1st subscriber: " + v));
obs.subscribe(v => console.log("2nd subscriber: " + v));
obs.connect();
//observer run 
//1st subscriber: 1474650370505 
//2nd subscriber: 1474650370505

可以看到 .publish() 之后, subscribe 不再能激活 observer 了,而必须手动调用 .connect() 才能激活 observer. 

这几个例子只是为了让你了解它们的玩法.

小结:

observer default is cold and not share.

cold 表示只有 subscribe 出现 observer 才会被激活.

not share 表示每一个 subscribe 都会激活 observer 链. 

 

常用 : 

1. finally 的使用

import 'rxjs/add/operator/finally';

this
.http.get( "http://localhost:58186/api/products", { headers: new Headers({ "Accept": "application/json" })} ).finally(() => { console.log("finally"); //不管 success or error 最后都会跑这个 }).subscribe(response => { console.log("success"); }, response => { console.log("fail"); }, () => { console.log("success final"); }); //result : //success -> success final -> finally //fail -> finally

 

2. 错误处理 throw catch  

 
  

import 'rxjs/add/operator/catch';
import { Observable } from "rxjs/Observable";
import 'rxjs/add/observable/throw';


this
.http.get( "http://localhost:58186/api/products", { headers: new Headers({ "Accept": "application/json" }) }) .map(r => r.json()) .catch((r) => { if ("1" == "1") { //do something ... return null; //catch 了在返回真确 } else { return Observable.throw("error"); //catch 了继续返回错误 } }) .subscribe( r => console.log(r), r => { console.log("fail") } );

 

3. previous / current value 

用 .pairwise()

let userSubject = new BehaviorSubject<string>("default value");
let user$ = userSubject.asObservable().pairwise();
user$.subscribe(([before, after]) => { console.log(before), console.log(after); });  
userSubject.next("super");
userSubject.next("ttc");
//result : 
//["default value","super"]
//["super","ttc"] 

 

转载于:https://www.cnblogs.com/keatkeat/p/5900998.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值