Rxjs Iif或简单的if

时间:2020-02-05 22:50:49

标签: javascript rxjs

我有以下代码:

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

我只是想知道为什么不能通过简单的if而不是iif来实现?

 if (condition) {
    return someObservable();
 }

2 个答案:

答案 0 :(得分: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));
<script src="https://unpkg.com/rxjs/bundles/rxjs.umd.min.js"></script>

除此之外,文档还指出iif是为了方便起见:

实际上,iif可以很容易地延迟实现,并且仅出于方便和易读性的原因而存在。

答案 1 :(得分:0)

如评论中所述:

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

使用true和false条件,这些语句将具有可比性:

  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

因此,您和您的团队认为这是最容易阅读的。