requestDidEnd only called after the last patch resolves

This commit is contained in:
clarencenpy 2018-08-08 16:30:27 -07:00
parent 1fa4105403
commit 927ca65ec7
2 changed files with 12 additions and 8 deletions

View file

@ -483,7 +483,7 @@ export async function runHttpQuery(
const isDeferred = isDeferredGraphQLResponse(graphqlResponse); const isDeferred = isDeferredGraphQLResponse(graphqlResponse);
let initialResponse: ExecutionResult; // We need this check for and and throw errors let initialResponse: ExecutionResult; // We need this check for and throw errors
if (isDeferred) { if (isDeferred) {
initialResponse = (graphqlResponse as DeferredGraphQLResponse) initialResponse = (graphqlResponse as DeferredGraphQLResponse)
@ -520,7 +520,9 @@ export async function runHttpQuery(
}; };
} }
// TODO: Handle defer in batched queries. This is a little awkward now since we need a separate HTTP connection to stream patches. // TODO: Handle defer in batched queries.
// This is a little awkward now since we need a separate HTTP connection
// to stream patches per query.
return { return {
graphqlResponse: prettyJSONStringify(responses), graphqlResponse: prettyJSONStringify(responses),
responseInit, responseInit,
@ -551,6 +553,8 @@ function graphqlResponseToAsyncIterable(
fromGraphQLError(error), fromGraphQLError(error),
); );
} }
// Call requestDidEnd when the last patch is resolved
if (done) result.requestDidEnd();
return { value: prettyJSONStringify(value), done }; return { value: prettyJSONStringify(value), done };
}); });
} }

View file

@ -46,9 +46,9 @@ export interface GraphQLResponse {
} }
export interface DeferredGraphQLResponse { export interface DeferredGraphQLResponse {
errors?: Array<GraphQLError & object>;
initialResponse: GraphQLResponse; initialResponse: GraphQLResponse;
deferredPatches: AsyncIterable<ExecutionPatchResult>; deferredPatches: AsyncIterable<ExecutionPatchResult>;
requestDidEnd: () => void;
} }
export function isDeferredGraphQLResponse( export function isDeferredGraphQLResponse(
@ -278,7 +278,6 @@ function doRunQuery(
let patches: AsyncIterable<ExecutionPatchResult> | undefined; let patches: AsyncIterable<ExecutionPatchResult> | undefined;
if (isDeferredExecutionResult(result)) { if (isDeferredExecutionResult(result)) {
// TODO: Deferred execution should be disabled if transport does not support it
executionResult = result.initialResult; executionResult = result.initialResult;
patches = result.deferredPatches; patches = result.deferredPatches;
} else { } else {
@ -312,6 +311,7 @@ function doRunQuery(
return { return {
initialResponse: response, initialResponse: response,
deferredPatches: patches!, deferredPatches: patches!,
requestDidEnd,
}; };
} else { } else {
return response; return response;
@ -327,16 +327,16 @@ function doRunQuery(
throw err; throw err;
}) })
.then((graphqlResponse: GraphQLResponse | DeferredGraphQLResponse) => { .then((graphqlResponse: GraphQLResponse | DeferredGraphQLResponse) => {
// For deferred queries, only the initial response gets presented to the // For deferred queries, pass the requestDidEnd callback as part of the
// extension stack // AsyncIterable so that it only gets called after all
// the patches have been resolved.
if (isDeferredGraphQLResponse(graphqlResponse)) { if (isDeferredGraphQLResponse(graphqlResponse)) {
const response = extensionStack.willSendResponse({ const response = extensionStack.willSendResponse({
graphqlResponse: graphqlResponse.initialResponse, graphqlResponse: graphqlResponse.initialResponse,
}); });
requestDidEnd();
return { return {
...graphqlResponse,
initialResponse: response.graphqlResponse, initialResponse: response.graphqlResponse,
deferredPatches: graphqlResponse.deferredPatches,
}; };
} else { } else {
const response = extensionStack.willSendResponse({ const response = extensionStack.willSendResponse({