Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Warning: Firebase API called outside injection context" on non-async functions #3611

Closed
anisabboud opened this issue Jan 12, 2025 · 2 comments · Fixed by #3613
Closed

"Warning: Firebase API called outside injection context" on non-async functions #3611

anisabboud opened this issue Jan 12, 2025 · 2 comments · Fixed by #3613

Comments

@anisabboud
Copy link

This is related to #3605 and #3607 where a workaround has been suggested #3590 (comment).
But my question is specifically for non-async functions.

First of all, thank you @jamesdaniels for the new guide at https://github.com/angular/angularfire/blob/main/docs/zones.md.
(I think the doc would benefit from some concrete examples.)

My understanding is that direct calls to docData where it's called say from within an rxjs switchMap, should be wrapped in runInInjectionContext

  loadDoc<T>(docPath: string): Observable<T | undefined> {
      return docData<T>(doc(this.firestore, docPath));
  }

↓↓↓

  private injectionContext = inject(EnvironmentInjector);

  loadDoc<T>(docPath: string): Observable<T | undefined> {
    return runInInjectionContext(this.injectionContext, () => {
      return docData<T>(doc(this.firestore, docPath));
    });
  }

However, even after adding runInInjectionContext wrappers for all load & set operations, there are still warnings from functions that are not async in nature such as where, snapToData, serverTimestamp, increment, orderBy, limit:

warnings on where, snapToData, serverTimestamp, increment, orderBy, limit

This is because tools/build.ts is applying ɵzoneWrap to every Firebase function:

export const collectionData = ɵzoneWrap(_collectionData, true);
export const docSnapshots = ɵzoneWrap(_doc, true);
export const docData = ɵzoneWrap(_docData, true);
export const fromRef = ɵzoneWrap(_fromRef, true);
export const snapToData = ɵzoneWrap(_snapToData, true);
export const sortedChanges = ɵzoneWrap(_sortedChanges, true);

export const addDoc = ɵzoneWrap(_addDoc, true);
export const aggregateFieldEqual = ɵzoneWrap(_aggregateFieldEqual, true);
export const aggregateQuerySnapshotEqual = ɵzoneWrap(_aggregateQuerySnapshotEqual, true);
export const and = ɵzoneWrap(_and, true);
export const arrayRemove = ɵzoneWrap(_arrayRemove, true);
export const arrayUnion = ɵzoneWrap(_arrayUnion, true);
export const average = ɵzoneWrap(_average, true);
export const clearIndexedDbPersistence = ɵzoneWrap(_clearIndexedDbPersistence, true);
export const collection = ɵzoneWrap(_collection, true);
export const collectionGroup = ɵzoneWrap(_collectionGroup, true);
export const connectFirestoreEmulator = ɵzoneWrap(_connectFirestoreEmulator, true);
export const count = ɵzoneWrap(_count, true);
export const deleteAllPersistentCacheIndexes = ɵzoneWrap(_deleteAllPersistentCacheIndexes, true);
export const deleteDoc = ɵzoneWrap(_deleteDoc, true);
export const deleteField = ɵzoneWrap(_deleteField, true);
export const disableNetwork = ɵzoneWrap(_disableNetwork, true);
export const disablePersistentCacheIndexAutoCreation = ɵzoneWrap(_disablePersistentCacheIndexAutoCreation, true);
export const doc = ɵzoneWrap(_doc, true);
export const documentId = ɵzoneWrap(_documentId, true);
export const enableIndexedDbPersistence = ɵzoneWrap(_enableIndexedDbPersistence, true);
export const enableMultiTabIndexedDbPersistence = ɵzoneWrap(_enableMultiTabIndexedDbPersistence, true);
export const enableNetwork = ɵzoneWrap(_enableNetwork, true);
export const enablePersistentCacheIndexAutoCreation = ɵzoneWrap(_enablePersistentCacheIndexAutoCreation, true);
export const endAt = ɵzoneWrap(_endAt, true);
export const endBefore = ɵzoneWrap(_endBefore, true);
export const getAggregateFromServer = ɵzoneWrap(_getAggregateFromServer, true);
export const getCountFromServer = ɵzoneWrap(_getCountFromServer, true);
export const getDoc = ɵzoneWrap(_getDoc, true);
export const getDocFromCache = ɵzoneWrap(_getDocFromCache, true);
export const getDocFromServer = ɵzoneWrap(_getDocFromServer, true);
export const getDocs = ɵzoneWrap(_getDocs, true);
export const getDocsFromCache = ɵzoneWrap(_getDocsFromCache, true);
export const getDocsFromServer = ɵzoneWrap(_getDocsFromServer, true);
export const getFirestore = ɵzoneWrap(_getFirestore, true);
export const getPersistentCacheIndexManager = ɵzoneWrap(_getPersistentCacheIndexManager, true);
export const increment = ɵzoneWrap(_increment, true);
export const initializeFirestore = ɵzoneWrap(_initializeFirestore, true);
export const limit = ɵzoneWrap(_limit, true);
export const limitToLast = ɵzoneWrap(_limitToLast, true);
export const loadBundle = ɵzoneWrap(_loadBundle, true);
export const memoryEagerGarbageCollector = ɵzoneWrap(_memoryEagerGarbageCollector, true);
export const memoryLocalCache = ɵzoneWrap(_memoryLocalCache, true);
export const memoryLruGarbageCollector = ɵzoneWrap(_memoryLruGarbageCollector, true);
export const namedQuery = ɵzoneWrap(_namedQuery, true);
export const onSnapshot = ɵzoneWrap(_onSnapshot, true);
export const onSnapshotsInSync = ɵzoneWrap(_onSnapshotsInSync, true);
export const or = ɵzoneWrap(_or, true);
export const orderBy = ɵzoneWrap(_orderBy, true);
export const persistentLocalCache = ɵzoneWrap(_persistentLocalCache, true);
export const persistentMultipleTabManager = ɵzoneWrap(_persistentMultipleTabManager, true);
export const persistentSingleTabManager = ɵzoneWrap(_persistentSingleTabManager, true);
export const query = ɵzoneWrap(_query, true);
export const queryEqual = ɵzoneWrap(_queryEqual, true);
export const refEqual = ɵzoneWrap(_refEqual, true);
export const runTransaction = ɵzoneWrap(_runTransaction, true);
export const serverTimestamp = ɵzoneWrap(_serverTimestamp, true);
export const setDoc = ɵzoneWrap(_setDoc, true);
export const setIndexConfiguration = ɵzoneWrap(_setIndexConfiguration, true);
export const setLogLevel = ɵzoneWrap(_setLogLevel, true);
export const snapshotEqual = ɵzoneWrap(_snapshotEqual, true);
export const startAfter = ɵzoneWrap(_startAfter, true);
export const startAt = ɵzoneWrap(_startAt, true);
export const sum = ɵzoneWrap(_sum, true);
export const terminate = ɵzoneWrap(_terminate, true);
export const updateDoc = ɵzoneWrap(_updateDoc, true);
export const vector = ɵzoneWrap(_vector, true);
export const waitForPendingWrites = ɵzoneWrap(_waitForPendingWrites, true);
export const where = ɵzoneWrap(_where, true);
export const writeBatch = ɵzoneWrap(_writeBatch, true);

Should AngularFire take a more granular approach and throw warnings only on async functions such as docData to avoid extraneous warnings?

@google-oss-bot
Copy link

This issue does not seem to follow the issue template. Make sure you provide all the required information.

@jamesdaniels
Copy link
Member

It may make sense to make this configurable. Perhaps tone down the number of warnings.

Def need to improve the doc but I'd rather be verbose since zone instability is a lot of support burden.

I wrap everything as we've been bitten in the past by seemingly innocent APIs like query and doc triggering side-effects which pulled in setTimeouts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants