Загрузите Firebase асинхронно, используя RxJS или любой другой пакет, а затем используйте его в проекте - PullRequest
0 голосов
/ 31 августа 2018

Мой вопрос не в том, как заставить это работать, а в том, как сделать это правильно ... Я экспериментирую с RxJS и пока не уверен, каков наилучший подход для этого конкретного варианта использования.

Этот подход был вдохновлен примером репозитория, опубликованным командой Firebase: rxfire-samples - response

Моя цель состоит в том, чтобы использовать firebase в приложении реакции, лениво загруженный с WebPack вместе с RxJS, и я планирую добавить в конце наблюдаемую при помощи редукса.

В данный момент я загружаю 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 }

1 Ответ

0 голосов
/ 31 августа 2018

Я бы предложил два улучшения. Во-первых, не выставляйте Subject или AsyncSubject на модули, которым нужно только подписаться на него. Вместо этого вы можете использовать firebaseApp.asObservable(), чтобы получить объект, который реализует только Observable.

Во-вторых, из-за раскрытия подписи Subject вы можете использовать unsubscribe в другом файле, что вам определенно не следует. Отписавшиеся темы сделают их непригодными для других подписчиков. Итак, просто удалите оператор unsubscribe. Бен Леш даже предлагает не использовать unsubscribe на всех l.

Теперь, кроме этих двух стилевых улучшений, с вашим подходом могут быть серьезные проблемы. AsyncSubject используется для инкапсуляции одной асинхронной операции. У него нет механизма кэширования, а это означает, что вы не можете подписаться несколько раз на одну и ту же тему и получать последнее значение. Субъекты всегда горячие , поэтому вы должны подписаться, прежде чем они будут отправлены. Чтобы обойти это, вы можете использовать ReplaySubject(1). Он будет кэшировать последнюю версию и воспроизводить ее всем будущим подписчикам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...