【问题标题】:modelling and if/else pattern inside an rxjs observable pipelinerxjs 可观察管道内的建模和 if/else 模式
【发布时间】:2019-08-21 07:28:19
【问题描述】:

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

如果 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 会被触发,但它不会等待响应,并且 dispatch 永远不会被触发。

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

任何指导将不胜感激。

【问题讨论】:

    标签: javascript if-statement rxjs rxjs6 redux-observable


    【解决方案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)...
    )
    

    【讨论】:

      【解决方案2】:

      但是您的代码可以稍微优化一下并建议以更好的方式进行,您在这里缺少的是 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'))
          );
      

      注意事项:

      • 不要嵌套管道操作符,尽量使用一根管道
      • 在 Rx 流之外提取复杂的方法
      • 使用of 运算符将普通对象转换为可观察对象

      【讨论】:

      • 我将另一个答案标记为正确,因为它首先被正确回答。但是非常感谢您花时间解释原因,这非常有帮助,我很感激。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-10
      • 2020-12-28
      • 2019-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多