奇怪的情况是没有使用BehaviorSubject调用map函数

时间:2018-02-02 19:19:14

标签: javascript angular functional-programming rxjs

我在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抛出错误。

2 个答案:

答案 0 :(得分:0)

Observable是懒惰的(大部分时间),它们在您订阅之前不会执行您声明的代码。订阅需要三个参数(nexterrorcomplete) - 可能执行或不执行的函数,具体取决于通过可观察链传递的内容。

在您的示例中,仅执行error回调,这个:

Rx.Observable
  .empty()
  .subscribe(...)

只会执行complete回调(你没有指定它)。

Rx.Observable
  .of(123)
  .subscribe(...)

会同时执行nextcomplete个回调。

基本规则是:

    如果没有错误,则会调用
  • 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打印两次。