From d68046fb9d0d43c802f314d10139084feb5f554a Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 27 Apr 2018 18:11:00 -0400 Subject: [PATCH] Fix references to uninitialized Promise variables. The following code should cause the promise to be rejected, because the `promise` variable will not be initialized until after the `new Promise(...)` expression finishes evaluating, which happens after the callback returns: const promise = new Promise((resolve, reject) => { console.log(promise); }); TypeScript compiles this code down to `var promise = ...` instead of `const promise = ...`, which is probably why the `ReferenceError` is not fatal, but the `promise` variable is definitely undefined either way. It's a shame that TypeScript thinks this code is perfectly fine, though temporal dead zone errors are admittedly difficult to simulate (efficiently, at least) using `var` declarations. Good thing the `promise` property of `QueryPromise` objects is never used! --- packages/apollo-client/src/core/QueryManager.ts | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/packages/apollo-client/src/core/QueryManager.ts b/packages/apollo-client/src/core/QueryManager.ts index 3390b52db56..ffc270642dc 100644 --- a/packages/apollo-client/src/core/QueryManager.ts +++ b/packages/apollo-client/src/core/QueryManager.ts @@ -60,7 +60,6 @@ const defaultQueryInfo = { }; export interface QueryPromise { - promise: Promise>; resolve: (result: ApolloQueryResult) => void; reject: (error: Error) => void; } @@ -681,8 +680,9 @@ export class QueryManager { options.notifyOnNetworkStatusChange = false; const requestId = this.idCounter; - const resPromise = new Promise>((resolve, reject) => { - this.addFetchQueryPromise(requestId, resPromise, resolve, reject); + + return new Promise>((resolve, reject) => { + this.addFetchQueryPromise(requestId, resolve, reject); return this.watchQuery(options, false) .result() @@ -695,8 +695,6 @@ export class QueryManager { reject(error); }); }); - - return resPromise; } public generateQueryId() { @@ -751,12 +749,10 @@ export class QueryManager { // Adds a promise to this.fetchQueryPromises for a given request ID. public addFetchQueryPromise( requestId: number, - promise: Promise>, resolve: (result: ApolloQueryResult) => void, reject: (error: Error) => void, ) { this.fetchQueryPromises.set(requestId.toString(), { - promise, resolve, reject, }); @@ -1060,8 +1056,9 @@ export class QueryManager { let resultFromStore: any; let errorsFromStore: any; - const retPromise = new Promise>((resolve, reject) => { - this.addFetchQueryPromise(requestId, retPromise, resolve, reject); + + return new Promise>((resolve, reject) => { + this.addFetchQueryPromise(requestId, resolve, reject); const subscription = execute(this.deduplicator, operation).subscribe({ next: (result: ExecutionResult) => { // default the lastRequestId to 1 @@ -1154,8 +1151,6 @@ export class QueryManager { subscriptions: subscriptions.concat([subscription]), })); }); - - return retPromise; } // Refetches a query given that query's name. Refetches