我在Angular App中关于地图未被调用的RxJS的weid案例前面。
请看一下这段代码:
const userSource = new Rx.BehaviorSubject(undefined);
const user = userSource.asObservable();
user.map(user => {
const shouldPass = !!user;
console.log('shouldPass', shouldPass, user);
if (user === null) {
console.log('go to login');
// this.router.navigate(['login']);
}
return shouldPass;
});
Rx.Observable
.throwError(new Error('HTTP 401'))
.subscribe(
user => userSource.next(user),
e => userSource.next(null)
);
这段代码(我翻译成普通的JavaScript)被放置在一个专门用于从服务器加载用户实体的函数中(此处用throw错误来代替模拟HTTP错误),然后emit
放在{{1}上}}。
在此示例中,BehaviorSubject
初始化期间仅user.map
被调用一次。
对我来说,它应该被召唤两次,对吗?一次初始化和另一次从observable抛出错误。
答案 0 :(得分:0)
Observable是懒惰的(大部分时间),它们在您订阅之前不会执行您声明的代码。订阅需要三个参数(next
,error
,complete
) - 可能执行或不执行的函数,具体取决于通过可观察链传递的内容。
在您的示例中,仅执行error
回调,这个:
Rx.Observable
.empty()
.subscribe(...)
只会执行complete
回调(你没有指定它)。
Rx.Observable
.of(123)
.subscribe(...)
会同时执行next
和complete
个回调。
基本规则是:
next
回调error
被调用然后没有错误complete
在observable完成且没有错误时被调用
有关详细信息,请参阅:
答案 1 :(得分:0)
问题是你在哪里订阅?到user
?因为这与订阅userSource.asObservable()
相同。
我想您要订阅user.map()
的结果,因此您需要将其分配给变量:
const userSource = new Rx.BehaviorSubject(undefined);
const user = userSource.asObservable();
const bla = user.map(user => {
const shouldPass = !!user;
// console.log('shouldPass', shouldPass, user);
if (user === null) {
// console.log('go to login');
// this.router.navigate(['login']);
}
return shouldPass;
});
bla.subscribe(console.log);
Rx.Observable
.throw(new Error('HTTP 401'))
.subscribe(
user => userSource.next(user),
e => userSource.next(null)
);
另请注意,您需要在bla
之前订阅Rx.Observable.throw()
,否则您会发出userSource.next(user)
,但没有人在听(没有观察者)。
使用上面的代码,您会看到false
打印两次。