Reactjs 使用RxJS或任何其他包异步加载Firebase,然后在整个项目中使用它

Reactjs 使用RxJS或任何其他包异步加载Firebase,然后在整个项目中使用它,reactjs,firebase,webpack,rxjs,firebase-authentication,Reactjs,Firebase,Webpack,Rxjs,Firebase Authentication,我的问题不是如何使它工作,而是如何使它正确。。。我正在试验RxJS,但还不确定针对该特定用例的最佳方法是什么 该方法受Firebase团队发布的回购示例的启发: 我的目标是在react应用程序中使用firebase,将WebPack与RxJS一起延迟加载,我计划最终添加redux observable 目前我正在加载firebase,如下所示: import { from, forkJoin, AsyncSubject } from 'rxjs' import { tap, map } from

我的问题不是如何使它工作,而是如何使它正确。。。我正在试验RxJS,但还不确定针对该特定用例的最佳方法是什么

该方法受Firebase团队发布的回购示例的启发:

我的目标是在react应用程序中使用firebase,将WebPack与RxJS一起延迟加载,我计划最终添加redux observable

目前我正在加载firebase,如下所示:

import { from, forkJoin, AsyncSubject } from 'rxjs'
import { tap, map } from 'rxjs/operators'
import { authListener } from '../auth/listener'

const CONFIG = {
 ...
}

const lazyLoadFireBase = (config) => {
    const app$ = from(import('firebase/app'))
    const firestore$ = from(import('firebase/firestore'))
    const fireAuth$ = from(import('firebase/auth'))

    return forkJoin(app$, firestore$, fireAuth$).pipe(
        map(([firebase]) => {
            const app = firebase.initializeApp(config)

            app.firestore().settings({ timestampsInSnapshots: true })

            app.firestore().enablePersistence()

            return app
        })
    )
}

const firebaseApp = new AsyncSubject()

lazyLoadFireBase(CONFIG)
    .pipe(
        tap((app) => {
            authListener(app)
        })
    )
    .subscribe((app) => firebaseApp.next(app))

export { firebaseApp }
如果我想用firebase做这样的事情,效果会很好,但感觉不是一个正确的方法。我想知道在整个项目中共享延迟加载的Firebase包的更好方法是什么

import { firebaseApp } from '../../../store/firebase'

const logOut = (ev) => {
    ev.preventDefault()

    firebaseApp.subscribe((app) => {
        app.auth().signOut()
    })

}
@ggradnig建议实施的变更:

import { from, forkJoin, ReplaySubject } from 'rxjs'
import { tap, map } from 'rxjs/operators'
import { authListener } from '../auth/listener'

const CONFIG = {
}

const lazyLoadFireBase = (config) => {
    const app$ = from(import('firebase/app'))
    const firestore$ = from(import('firebase/firestore'))
    const fireAuth$ = from(import('firebase/auth'))

    return forkJoin(app$, firestore$, fireAuth$).pipe(
        map(([firebase]) => {
            const app = firebase.initializeApp(config)

            app.firestore().settings({ timestampsInSnapshots: true })

            app.firestore().enablePersistence()

            return app
        })
    )
}

const firebaseApp = new ReplaySubject(1)

lazyLoadFireBase(CONFIG)
    .pipe(
        tap((app) => {
            authListener(app)
        })
    )
    .subscribe((app) => firebaseApp.next(app))

firebaseApp.asObservable()

export { firebaseApp }

我建议有两个改进。首先,不要将Subject或AsyncSubject公开给只需要订阅它的模块。相反,您可以使用firebaseApp.asObservable来获取仅实现Observable的对象

其次,由于主题签名的暴露,您可以在另一个文件中使用unsubscribe,这是您绝对不应该使用的。取消订阅主题将使其他订阅者无法使用它们。所以,只需删除unsubscribe语句。l


现在,除了这两种风格的改进之外,您的方法可能存在真正的问题。AsyncSubject用于封装单个异步操作。它没有缓存机制,这意味着您不能多次订阅同一主题并接收最新的值。主题总是很热门,所以你必须在它发布之前订阅。要解决这个问题,可以使用ReplaySubject1。它将缓存最新的发射,并将其重播给所有未来的订户。

感谢您的反馈,我实施了您的更改,效果很好。