问题描述
我有一些javascript:
this.mySubscription = someObservable.subscribe((obs: any) => {
this.mySubscription.unsubscribe();
this.mySubscription = undefined;
}
执行时,控制台记录错误ERROR TypeError: Cannot read property 'unsubscribe' of undefined
。
我想知道为什么我不能取消订阅lambda函数。有正确的方法吗?我已经阅读了一些有关使用虚拟对象并完成它们或使用takeuntil / takeWhile和其他管道运算符workArounds的知识。
我目前正在使用虚拟订阅,例如:
mySubscription: BehaviorSubject<any> = new BehaviorSubject<any>(undefined);
// when I do the subscription:
dummySubscription: BehaviorSubject<any> = new BehavIoUrSubject<any>(this.mySubscription.getValue());
this.mySubscription = someObservable.subscribe((obs: any) => {
// any work...
dummySubscription.next(obs);
dummySubscription.complete();
dummySubscription = undefined;
},error => {
dummySubscription.error(error);
});
dummySubscription.subscribe((obs: any) => {
// here the actual work to do when mySubscription emits a value,before it should have been unsubscribed upon
},err => {
// if errors need be
});
解决方法
您不应尝试在subscribe
函数中退订。
您可以取消订阅take
,takeWhile
或takeUntil
之类的运算符。
服用
在take(n)
发出someObservable
次之后,使用n
退订。
someObservable.pipe(
take(1)
).subscribe(value => console.log(value));
takeWhile
当发射的值不符合条件时,使用takeWhile
取消订阅。
someObservable.pipe(
takeWhile(value => valueIsSave(value))
).subscribe(value => console.log(value));
valueIsSave(value): boolean {
// return true if the subscription should continue
// return false if you want to unsubscribe on that value
}
takeUntil
当观察到的takeUntil(obs$)
发出时,请使用obs$
退订。
const terminate = new Subject();
someObservable.pipe(
takeUntil(terminate)
).subscribe(value => console.log(value));
unsub() {
terminate.next() // trigger unsubscribe
}
,
如果使流异步,则您正在执行的操作应该可以进行。例如,这将不起作用:
const sub = from([1,2,3,4,5,6,7,8,9,10]).subscribe(val => {
console.log(val);
if(val > 5) sub.unsubscribe();
});
但这将起作用:
const sub2 = from([1,10]).pipe(
delay(0)
).subscribe(val => {
console.log(val);
if(val > 5) sub2.unsubscribe();
});
由于JS事件循环是相当可预测的(代码块始终运行到完成),如果流的任何部分都是异步的,则可以确定将在调用lambda回调之前定义订阅。 / p>
您应该这样做吗?
可能不是。如果您的代码依赖于您的语言/编译器/解释器/等的内部(否则为隐藏的)机密,则您已经创建了易碎的代码和/或难以维护的代码。下一位正在查看我的代码的开发人员将对为什么会有delay(0)
感到困惑-看来它不应该做任何事情。
请注意,在subscribe()
中,您的lambda可以访问其闭包以及当前的流变量。 takeWhile()
运算符可以访问相同的闭包和相同的流变量。
from([1,10]).pipe(
takeWhile(val => {
// add custom logic
return val <= 5;
})
).subscribe(val => {
console.log(val);
});
takeWhile()
可以处理sub = subscribe(... sub.unsubscibe() ... )
的任何内容,并具有不需要管理订阅对象并且易于读取/维护的额外好处。