rxjs 技巧
skip rxjs
忽略前两次执行
skip(2)
星号背后的意义*
<h1 *myNgIf>
Angular rocks
</h1>
等价
<ng-template myNgIf>
<h1>
Angular rocks
</h1>
</ng-template>
写个小案例
export class MyNgIfDirective implements OnInit {
@Input() appMyNgIf: boolean = false;
constructor(
private view: ViewContainerRef,
private template: TemplateRef<any>
) {}
ngOnChanges() {
if (this.appMyNgIf) {
this.view.createEmbeddedView(this.template);
} else {
this.view.clear();
}
}
}
BehaviorSubject
需要一个初始值并将当前值发送给新订阅者
subject = new BehaviorSubject(123);
this.subject.subscribe(console.log); // 123, 345
this.subject.next(345);
// 给个值,然后修改初始值
subject = new BehaviorSubject<any>('3333');
let a=this.subject.asObservable();
a.next(10);
a.subscribe(console.log) // 10
区别
let beSub = new BehaviorSubject<number>(0); // 默认就返回初始化的值
beSub.subscribe(console.log) // 默认 0
let sub=new Subject();
sub.next(1);
sub.subscribe(console.log);// 2
sub.next(2)
ReplaySubject
以发送旧值给新的订阅者,但是不仅是‘当前值’,还可以是之前的旧值。
// 最后4次的值
subject: ReplaySubject<any> = new ReplaySubject<any>(4);
this.subject.next(2);
this.subject.next(3);
this.subject.next(4);
this.subject.next(5);
this.subject.next(6);
this.subject.next(7);
let a=this.subject.asObservable();
a.subscribe(console.log) // 4,5,6,7
AsyncSubject
只有当 Observable 执行完成时(执行 complete()),它才会将执行的最后一个值发送给观察者。
private subject: AsyncSubject<number> = new AsyncSubject<number>();
this.subject.next(2);
this.subject.next(3);
this.subject.next(4);
this.subject.next(5);
this.subject.next(6);
this.subject.complete();
this.subject.next(7);
let a=this.subject.asObservable();
a.subscribe(console.log) // 6
tap
-
tap
操作符确实为使用它的每个项目运行回调,用于副作用,但返回一个与源相同的 observable。 -
也可以用作注释,比如打印下每项做了哪些操作
const objects = [
{ id: 1, name: 'Fabian' },
{ id: 2, name: 'Jan-Niklas' },
];
from(objects).pipe(tap(item=>(item.name=item.name+'xxx'))).subscribe(console.log)
// { id: 1, name: "Fabian_2" }
// { id: 2, name: "Jan-Niklas_2" }
Map
应用于源 Observable 发出的每个值,并将结果值作为 Observable 发出。
const objects = [ {id: 1, name: 'Fabian'}, {id: 2, name: 'Jan-Niklas'}, ];from(objects).pipe(map(v => v.id + 1)).subscribe(console.log)
MapTo
我觉得应用就是类似于请求超时
// delay 模拟请求延时of(1).pipe(delay(1000),mapTo('失败')).subscribe(console.log)
concat concatMap
concat(of(1),of(2),of(3)).subscribe(console.log)// 1,2,3of(1,'a').pipe(concatMap(v => of(v+'a'))).subscribe(console.log)// 1a,aa
同步的情况下concat
===merge
异步用merge
const a=interval(1000).pipe(map(v => v * 100));
const b=interval(2000).pipe(map(v => v * 1000));
concat(a,b).pipe(take(10)).subscribe(console.log)
我们发现b一直不执行,因为是同步的
concat(interval(1000).pipe(map(v => v * 100)),interval(2000).pipe(map(v => v * 1000))).pipe(take(10)).subscribe(console.log)
// 我们发现是交错执行的
switchMap、mergeMap、concatMap和exhaustMap 区别
// 模拟异步请求
const prepOrder = (order: string) => {
const delayTime = Math.floor(Math.random() * 100);
return of(order).pipe(delay(delayTime))
};
from(['aaa', 'bbb', 'ccc', 'ddd']).pipe(
//异步展示
// mergeMap(v => prepOrder(v))
//同步展示
// concatMap(v => prepOrder(v))
// 只对最后一次有响应
// switchMap(v=>prepOrder(v))
// 只对第一次有响应
exhaustMap(v=>prepOrder(v))
).subscribe(console.log)
from([1,2,3]).pipe(mergeMap(v=>of(v).pipe(delay(500)))).subscribe(console.log)
// 1,2,3
from([1,2,3]).pipe(switchMap(v=>of(v).pipe(delay(500)))).subscribe(console.log)
// 3
from([1,2,3]).pipe(exhaustMap(v=>of(v).pipe(delay(500)))).subscribe(console.log)
// 1
-🤯 mergeMap:我是一个勤奋的人,我可以同时准备多个订单!但我不尊重订单顺序。
-😇 concatMap:我尊重订单顺序!一旦我完成我目前正在做的事情,你就会得到你的订单。
-🙄exhaustMap :我已经筋疲力尽了!当我准备订单时,我不会听任何其他订单。
-😈 switchMap:我是说!如果我收到新的订单,您的订单将被丢弃。
@Input
_vName:string;
@Input()
get vName(){
return this._vName
}
set vName(name:string){
this._vName=name;
}
async
num=of(1);
<h1 *ngIf="num|async as date1">{{date1}}</h1>
多个api请求
prepOrder(order: string | number) {
const delayTime = Math.floor(Math.random() * 100);
return of(order).pipe(delay(delayTime))
};
from([1, 2, 3, 4]).pipe(
// 模拟请求
mergeMap(item => this.prepOrder(item)),
// 让一个个请求
concatMap(item => of(item).pipe(delay(1000)))
).subscribe(console.log);
angular 最新版
npx @angular/cli new xxx
promise=> observable
from(new Promise(res=>res('xxx'))).subscribe(console.log)
// xxx
share() 多播
没加share()
let a = interval(1000).pipe(map(x => {
console.log('测试'+x);
return x * x
}),
take(2),
)
a.subscribe(v=>{
console.log('sub1-' + v);
})
a.subscribe(v=>{
console.log('sub2-' + v);
})
// 测试0
// sub1-0
// 测试0
// sub2-0
// 测试1
// sub1-1
// 测试1
// sub2-1
加入
pipe(map(x => {
console.log('测试'+x);
return x * x
}),
take(2),
share()
)
// 测试0
// sub1-0
// sub2-0
// 测试1
// sub1-1
// sub2-1
NEVER
则是返回一个永不完结的Observable
,不会调用观察者的任何函数
NEVER.subscribe(() => {
console.log('执行');
}, console.log, () => {
console.log('执行了--');
});
EMPTY
EMPTY是直接返回一个完成的Observable,会直接调用观察者的completed函数
throwError('error').pipe(
catchError(() => {
return EMPTY
})
).subscribe(() => {
console.log('执行');
}, console.log, () => {
console.log('执行了--');
});
// 执行了--
repeatWhen
repeat
能够重复订阅上游的Observable
,但是不能控制订阅时间,如等待 2 秒再重新订阅
of(1, 2, 3).pipe(
repeatWhen(v => v.pipe(delay(2000))),
take(8)
).subscribe(console.log)
concat和 merge
let a = timer(2000).pipe(mapTo('TO1'));
let b = timer(1000).pipe(mapTo('TO2'));
merge(a, b).subscribe(console.log);
// To2 To1, 异常
concat(a,b).subscribe(console.log)
// To1 To2 同步
of(1, 2).pipe(
// mergeMap(v => [a, b][v - 1])
concatMap(v => [of(1),of(2)][v - 1])
).subscribe(console.log);
zip
zip(of('a','b','c'),of(1,2,3),of('v','x','y')).subscribe(console.log)
// ['a', 1, 'v']
// ['b', 2, 'x']
// ['c', 3, 'y']
let age$ = of(27, 25, 29);
let name$ = of('Foo', 'Bar', 'Beer');
let isDev$ = of(true, true, false);
zip(age$, name$, isDev$).pipe(
map(([age, name, isDev]) => ({ age, name, isDev }))
)
.subscribe(x => console.log(x));
// { age: 27, name: 'Foo', isDev: true }
// { age: 25, name: 'Bar', isDev: true }
// { age: 29, name: 'Beer', isDev: false }
zipAll
const source1 = of(1,2,3);
const source2 = of('a','b','c');
of(source1, source2)
.pipe(zipAll())
.subscribe(val => console.log(val));
// [1, 'a']
// [2, 'b']
// [3, 'c']
JorkJoin
当所有 observable 完成后,从每个 observable 发出最后发出的值。
const myPromise = (val: string) =>
new Promise(resolve =>
setTimeout(() => resolve(`Promise Resolved: ${val}`), 2000)
);
// 一组observable值 只关心每个的最终发出值
forkJoin({
my1: myPromise('my1'),
my2: myPromise('my2'),
}).subscribe(console.log)
// {my1: 'Promise Resolved: my1', my2: 'Promise Resolved: my2'}
ngIf /then
<div *ngIf="list | async as items;then list1"></div><ng-template #list1 let-items> <div *ngFor="let item of items">{{item}}</div></ng-template>of([1,2,3,4])
决定自己的高度的是你的态度,而不是你的才能
记得我们是终身初学者和学习者
总有一天我也能成为大佬