在rxjs可观察管道内建模和if / else模式

问题描述 投票:0回答:2

我有一个史诗,我正在听一个动作流,当一个'AUTH_STATUS_CHECKED'的动作发生切换到一个新的可观察的authState(app.auth())。这个新的观察结果告诉我,我是否经过身份验证。

如果auth observable返回用户,则以用户作为有效负载调度'SIGNED_IN'操作。

如果一个用户不存在,那么在一个承诺app.auth().signInWithPopup(googleAuthProvider)之前,当你得到响应调度'SIGNED_IN'

如果有任何错误,请抓住它们并在控制台中告诉我。

基于上面的逻辑,我已经实现了下面的管道

export const fetchAuthStatus = action$ =>
      action$.pipe(
        ofType('AUTH_STATUS_CHECKED'),
        switchMap(() =>
          authState(app.auth()).pipe(
            map(user =>
              user
                ? { type: 'SIGNED_IN', payload: user }
                : app
                    .auth()
                    .signInWithPopup(googleAuthProvider)
                    .then(user => ({ type: 'SIGNED_IN', payload: user }))
            ),
            catchError(error => console.log('problems signing in'))
          )
        )
      );

它没有按预期工作。如果没有用户,则会触发promise,但它不会等待响应,并且调度永远不会被触发。

我显然是rxjs的新手,我很难搞清楚这一点。我已经浏览了文档并尝试使用tap()和mergeMap()但是我得到了同样的错误。

任何指导将不胜感激。

javascript if-statement rxjs rxjs6 redux-observable
2个回答
1
投票

如果你需要等到一些内部Observable / Promise完成,你需要用例如包裹它。 mergeMapconcatMap。由于这两个运算符都要求您返回Observable / Promise,因此您必须使用of()将操作包装为将一个普通对象转换为Observable:

import { of } from 'rxjs';
import { mergeMap } from 'rxjs/operators';

...
mergeMap(user => user
  ? of({ type: 'SIGNED_IN', payload: user })
  : app.auth().signInWithPopup(googleAuthProvider)...
)

1
投票

但是你的代码可以稍微优化一下,并建议以更好的方式进行,你在这里缺少的是map期望一个普通的对象,而switchMap期望一个PromiseObservable对象。

const signIn = (authProvider) => app.auth().signInWithPopup(googleAuthProvider)
    .then(user => ({ type: 'SIGNED_IN', payload: user }));

export const fetchAuthStatus = action$ =>
    action$.pipe(
        ofType('AUTH_STATUS_CHECKED'),
        switchMap(() => authState(app.auth())),
        switchMap(user => user // <-- switchMap handle Promises or Observables
            ? of({ type: 'SIGNED_IN', payload: user }) // <-- returning an observable
            : signIn(googleAuthProvider) // <-- returning a promise
        ),
        catchError(error => console.log('problems signing in'))
    );

Notes:

  • 不要嵌套管道操作员,尽量使用一根管道
  • 在Rx流之外提取复杂的方法
  • 使用of运算符将普通对象转换为Observable
© www.soinside.com 2019 - 2024. All rights reserved.