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

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

我的问题不是如何使其工作,而是如何使其正确...我正在尝试使用RxJS并且不确定该特定用例的最佳方法是什么。

这种方法的灵感来自Firebase团队发布的示例回购:rxfire-samples - 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 }
reactjs firebase webpack rxjs firebase-authentication
1个回答
1
投票

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

其次,由于Subject签名的曝光,你可以在另一个文件中使用unsubscribe,你绝对不应该这样做。取消订阅主题将使其无法用于其他订阅者。所以,只需删除unsubscribe语句。 Ben Lesh even suggests not using unsubscribe at all。

现在,除了这两种风格改进之外,您的方法可能会遇到麻烦。 AsyncSubject用于封装单个异步操作。它没有缓存机制,这意味着您无法在同一主题上多次订阅并获得最新值。主题总是热门,因此您必须在发出之前订阅。要解决这个问题,你可以使用ReplaySubject(1)。它将缓存最新的发射并将其重播给所有未来的用户。

© www.soinside.com 2019 - 2024. All rights reserved.