diff --git a/packages/functions/src/api/service.ts b/packages/functions/src/api/service.ts index c0e757a4fa8..c02c6c5e4d7 100644 --- a/packages/functions/src/api/service.ts +++ b/packages/functions/src/api/service.ts @@ -16,6 +16,7 @@ */ import { FirebaseApp } from '@firebase/app-types'; +import { FirebaseService } from '@firebase/app-types/private'; import firebase from '@firebase/app'; import { FirebaseFunctions, @@ -53,10 +54,12 @@ function failAfter(millis: number): Promise { /** * The main class for the Firebase Functions SDK. */ -export class Service implements FirebaseFunctions { +export class Service implements FirebaseFunctions, FirebaseService { private readonly contextProvider: ContextProvider; private readonly serializer = new Serializer(); private emulatorOrigin: string | null = null; + private cancelAllRequests: Promise; + private deleteService: Function; /** * Creates a new Functions service for the given app and (optional) region. @@ -68,12 +71,24 @@ export class Service implements FirebaseFunctions { private region_: string = 'us-central1' ) { this.contextProvider = new ContextProvider(app_); + // Cancels all ongoing requests when resolved. + this.cancelAllRequests = new Promise(resolve => { + this.deleteService = () => { + return resolve(); + }; + }); } get app(): FirebaseApp { return this.app_; } + INTERNAL = { + delete: (): Promise => { + return this.deleteService(); + } + }; + /** * Returns the URL for a callable with the given name. * @param name The name of the callable. @@ -184,9 +199,18 @@ export class Service implements FirebaseFunctions { const response = await Promise.race([ this.postJSON(url, body, headers), - failAfter(timeout) + failAfter(timeout), + this.cancelAllRequests ]); + // If service was deleted, interrupted response throws an error. + if (!response) { + throw new HttpsErrorImpl( + 'cancelled', + 'Firebase Functions instance was deleted.' + ); + } + // Check for an error status, regardless of http status. const error = _errorForResponse( response.status,