Skip to content

Commit 8b5476a

Browse files
authored
Merge pull request #1007 from wincent/glh/graphql-update-fix
Rewrite createSourceEventStream to avoid use of `async`
2 parents d7a80b6 + 609af80 commit 8b5476a

File tree

1 file changed

+71
-66
lines changed

1 file changed

+71
-66
lines changed

src/subscription/subscribe.js

Lines changed: 71 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ function subscribeImpl(
188188
* or otherwise separating these two steps. For more on this, see the
189189
* "Supporting Subscriptions at Scale" information in the GraphQL specification.
190190
*/
191-
export async function createSourceEventStream(
191+
export function createSourceEventStream(
192192
schema: GraphQLSchema,
193193
document: DocumentNode,
194194
rootValue?: mixed,
@@ -205,77 +205,82 @@ export async function createSourceEventStream(
205205
variableValues
206206
);
207207

208-
// If a valid context cannot be created due to incorrect arguments,
209-
// this will throw an error.
210-
const exeContext = buildExecutionContext(
211-
schema,
212-
document,
213-
rootValue,
214-
contextValue,
215-
variableValues,
216-
operationName,
217-
fieldResolver
218-
);
219-
220-
const type = getOperationRootType(schema, exeContext.operation);
221-
const fields = collectFields(
222-
exeContext,
223-
type,
224-
exeContext.operation.selectionSet,
225-
Object.create(null),
226-
Object.create(null)
227-
);
228-
const responseNames = Object.keys(fields);
229-
const responseName = responseNames[0];
230-
const fieldNodes = fields[responseName];
231-
const fieldNode = fieldNodes[0];
232-
const fieldDef = getFieldDef(schema, type, fieldNode.name.value);
233-
invariant(
234-
fieldDef,
235-
'This subscription is not defined by the schema.'
236-
);
237-
238-
// Call the `subscribe()` resolver or the default resolver to produce an
239-
// AsyncIterable yielding raw payloads.
240-
const resolveFn = fieldDef.subscribe || exeContext.fieldResolver;
208+
return new Promise((resolve, reject) => {
209+
// If a valid context cannot be created due to incorrect arguments,
210+
// this will throw an error.
211+
const exeContext = buildExecutionContext(
212+
schema,
213+
document,
214+
rootValue,
215+
contextValue,
216+
variableValues,
217+
operationName,
218+
fieldResolver
219+
);
241220

242-
const path = addPath(undefined, responseName);
221+
const type = getOperationRootType(schema, exeContext.operation);
222+
const fields = collectFields(
223+
exeContext,
224+
type,
225+
exeContext.operation.selectionSet,
226+
Object.create(null),
227+
Object.create(null)
228+
);
229+
const responseNames = Object.keys(fields);
230+
const responseName = responseNames[0];
231+
const fieldNodes = fields[responseName];
232+
const fieldNode = fieldNodes[0];
233+
const fieldDef = getFieldDef(schema, type, fieldNode.name.value);
234+
invariant(
235+
fieldDef,
236+
'This subscription is not defined by the schema.'
237+
);
243238

244-
const info = buildResolveInfo(
245-
exeContext,
246-
fieldDef,
247-
fieldNodes,
248-
type,
249-
path
250-
);
239+
// Call the `subscribe()` resolver or the default resolver to produce an
240+
// AsyncIterable yielding raw payloads.
241+
const resolveFn = fieldDef.subscribe || exeContext.fieldResolver;
251242

252-
// resolveFieldValueOrError implements the "ResolveFieldEventStream"
253-
// algorithm from GraphQL specification. It differs from
254-
// "ResolveFieldValue" due to providing a different `resolveFn`.
255-
const subscription = await resolveFieldValueOrError(
256-
exeContext,
257-
fieldDef,
258-
fieldNodes,
259-
resolveFn,
260-
rootValue,
261-
info
262-
);
243+
const path = addPath(undefined, responseName);
263244

264-
// Throw located GraphQLError if subscription source fails to resolve.
265-
if (subscription instanceof Error) {
266-
throw locatedError(
267-
subscription,
245+
const info = buildResolveInfo(
246+
exeContext,
247+
fieldDef,
268248
fieldNodes,
269-
responsePathAsArray(path),
249+
type,
250+
path
270251
);
271-
}
272252

273-
if (!isAsyncIterable(subscription)) {
274-
throw new Error(
275-
'Subscription must return Async Iterable. ' +
276-
'Received: ' + String(subscription)
277-
);
278-
}
253+
// resolveFieldValueOrError implements the "ResolveFieldEventStream"
254+
// algorithm from GraphQL specification. It differs from
255+
// "ResolveFieldValue" due to providing a different `resolveFn`.
256+
Promise.resolve(resolveFieldValueOrError(
257+
exeContext,
258+
fieldDef,
259+
fieldNodes,
260+
resolveFn,
261+
rootValue,
262+
info
263+
)).then((subscription: any) => {
264+
// Reject with a located GraphQLError if subscription source fails
265+
// to resolve.
266+
if (subscription instanceof Error) {
267+
const error = locatedError(
268+
subscription,
269+
fieldNodes,
270+
responsePathAsArray(path),
271+
);
272+
reject(error);
273+
}
274+
275+
if (!isAsyncIterable(subscription)) {
276+
reject(new Error(
277+
'Subscription must return Async Iterable. ' +
278+
'Received: ' + String(subscription)
279+
));
280+
}
279281

280-
return (subscription: any);
282+
resolve(subscription);
283+
})
284+
.catch(reject);
285+
});
281286
}

0 commit comments

Comments
 (0)