【问题标题】:Rxjs iif or simple ifRxjs iif 或简单的 if
【发布时间】:2020-05-21 22:14:14
【问题描述】:

我有以下代码:

obs.pipe(
   switchMap((val) => {
       // some logic...
       return iif(() => condition, someObservable())
   })
);

我只是想知道为什么不能用简单的if 而不是iif 来实现这一点?

 if (condition) {
    return someObservable();
 }

【问题讨论】:

  • 在第一种情况下,如果条件为假,则生成的流立即完成。在第二种情况下,如果条件为假,您似乎没有返回任何流。为了进行比较,第二个示例需要有一个 else 并返回 EMPTYiif 的文档在这里:rxjs.dev/api/index/function/iif"

标签: javascript rxjs


【解决方案1】:

看看iif的实现:

export function iif<T = never, F = never>(
  condition: () => boolean,
  trueResult: SubscribableOrPromise<T> = EMPTY,
  falseResult: SubscribableOrPromise<F> = EMPTY
): Observable<T|F> {
  return defer(() => condition() ? trueResult : falseResult);
}

iif 使用defer 仅调用条件函数并在订阅(外部)Observable 时选择(内部)Observable。这在 switchMap 中使用时并没有真正的区别,因为 switchMap 中的代码在每次发出时都会执行,但是当您使用 iif 创建一个 Observable 并在以后订阅它时会导致不同的行为。

const { iif, of, concat } = rxjs;

let subscribeToFirst;
const obs$ = concat(
  iif(() => subscribeToFirst, of('iif-first'), of('iif-second')), // use 'iif'
  subscribeToFirst ? of('if-first (never logged)') : of('if-second') // use 'if'
);

// Change at runtime which Observable will be subscribed
// works for 'iif' but not for 'if'
console.log('----- subscribe to first -----');
subscribeToFirst = true;
obs$.subscribe(value => console.log(value));
console.log('----- subscribe to second -----');
subscribeToFirst = false;
obs$.subscribe(value => console.log(value));
&lt;script src="https://unpkg.com/rxjs/bundles/rxjs.umd.min.js"&gt;&lt;/script&gt;

除此之外,文档还说iif 的存在是为了方便:

实际上 iif 可以通过 defer 轻松实现,并且仅出于方便和可读性的原因而存在。

【讨论】:

  • 非常感谢您抽出宝贵的时间!这样if-first (never logged)' 就不会被记录,因为obs$subscribeToFirst 设置为true 之前已经订阅了?
  • @AngularDebutant 否。它没有被记录,因为表达式 subscribeToFirst ? of('if-first (never logged)') : of('if-second')subscribeToFirst = true; 之前执行。那时subscribeToFirst 仍然未定义,of('if-second') 被选中。
【解决方案2】:

如 cmets 中所述:

在第一种情况下,如果条件为假,则生成的流立即完成。在第二种情况下,如果条件为假,您似乎没有返回任何流。为了进行比较,第二个示例需要有一个 else 并返回 EMPTY。 iif 的文档在这里:rxjs.dev/api/index/function/iif

同时使用真假条件,这些陈述是可比较的:

  getUser() {
    const url = `${this.userUrl}/${this.currentUserId}`;
    this.todosForUser$ = this.http.get<User[]>(url).pipe(
      switchMap(user => {
        return iif(
          () => this.todos,
          this.http.get<ToDo[]>(`${this.todoUrl}?userId=${this.currentUserId}`),
          this.http.get<Post[]>(`${this.postUrl}?userId=${this.currentUserId}`)
        );
      })
    );
  }

  getUser() {
    const url = `${this.userUrl}/${this.currentUserId}`;
    this.todosForUser$ = this.http.get<User[]>(url).pipe(
      switchMap(user => {
        if (this.todos) {
          return this.http.get<ToDo[]>(`${this.todoUrl}?userId=${this.currentUserId}`);
        } else {
          return this.http.get<Post[]>(`${this.postUrl}?userId=${this.currentUserId}`);
        }
      })
    );
  }

您可以在这里找到堆栈闪电战:https://stackblitz.com/edit/angular-todos-deborahk-iif

所以归结为您和您的团队认为最容易阅读的内容。

【讨论】:

  • 感谢您的回复和解释!因此,如果我理解正确,iif 没有任何真正的用例,而不是使用简单的 if / else,除了 iif 处理 EMPTY 的返回,如果没有 observable 传递给 true/false 条件?跨度>
猜你喜欢
  • 2020-05-14
  • 2014-10-30
  • 1970-01-01
  • 2019-06-03
  • 1970-01-01
  • 1970-01-01
  • 2012-08-05
  • 2011-10-31
  • 1970-01-01
相关资源
最近更新 更多