|
9 | 9 |
|
10 | 10 | import { forEach, isCollection } from 'iterall'; |
11 | 11 | import { GraphQLError, locatedError } from '../error'; |
| 12 | +import getPromise from '../jsutils/getPromise'; |
12 | 13 | import invariant from '../jsutils/invariant'; |
13 | 14 | import isInvalid from '../jsutils/isInvalid'; |
14 | 15 | import isNullish from '../jsutils/isNullish'; |
15 | 16 | import memoize3 from '../jsutils/memoize3'; |
| 17 | +import promiseForObject from '../jsutils/promiseForObject'; |
| 18 | +import promiseReduce from '../jsutils/promiseReduce'; |
16 | 19 | import type { ObjMap } from '../jsutils/ObjMap'; |
17 | 20 | import type { MaybePromise } from '../jsutils/MaybePromise'; |
18 | 21 |
|
@@ -465,33 +468,33 @@ function executeFieldsSerially( |
465 | 468 | sourceValue: mixed, |
466 | 469 | path: ResponsePath | void, |
467 | 470 | fields: ObjMap<Array<FieldNode>>, |
468 | | -): Promise<ObjMap<mixed>> { |
469 | | - return Object.keys(fields).reduce( |
470 | | - (prevPromise, responseName) => |
471 | | - prevPromise.then(results => { |
472 | | - const fieldNodes = fields[responseName]; |
473 | | - const fieldPath = addPath(path, responseName); |
474 | | - const result = resolveField( |
475 | | - exeContext, |
476 | | - parentType, |
477 | | - sourceValue, |
478 | | - fieldNodes, |
479 | | - fieldPath, |
480 | | - ); |
481 | | - if (result === undefined) { |
482 | | - return results; |
483 | | - } |
484 | | - const promise = getPromise(result); |
485 | | - if (promise) { |
486 | | - return promise.then(resolvedResult => { |
487 | | - results[responseName] = resolvedResult; |
488 | | - return results; |
489 | | - }); |
490 | | - } |
491 | | - results[responseName] = result; |
| 471 | +): MaybePromise<ObjMap<mixed>> { |
| 472 | + return promiseReduce( |
| 473 | + Object.keys(fields), |
| 474 | + (results, responseName) => { |
| 475 | + const fieldNodes = fields[responseName]; |
| 476 | + const fieldPath = addPath(path, responseName); |
| 477 | + const result = resolveField( |
| 478 | + exeContext, |
| 479 | + parentType, |
| 480 | + sourceValue, |
| 481 | + fieldNodes, |
| 482 | + fieldPath, |
| 483 | + ); |
| 484 | + if (result === undefined) { |
492 | 485 | return results; |
493 | | - }), |
494 | | - Promise.resolve({}), |
| 486 | + } |
| 487 | + const promise = getPromise(result); |
| 488 | + if (promise) { |
| 489 | + return promise.then(resolvedResult => { |
| 490 | + results[responseName] = resolvedResult; |
| 491 | + return results; |
| 492 | + }); |
| 493 | + } |
| 494 | + results[responseName] = result; |
| 495 | + return results; |
| 496 | + }, |
| 497 | + Object.create(null), |
495 | 498 | ); |
496 | 499 | } |
497 | 500 |
|
@@ -662,24 +665,6 @@ function doesFragmentConditionMatch( |
662 | 665 | return false; |
663 | 666 | } |
664 | 667 |
|
665 | | -/** |
666 | | - * This function transforms a JS object `ObjMap<Promise<T>>` into |
667 | | - * a `Promise<ObjMap<T>>` |
668 | | - * |
669 | | - * This is akin to bluebird's `Promise.props`, but implemented only using |
670 | | - * `Promise.all` so it will work with any implementation of ES6 promises. |
671 | | - */ |
672 | | -function promiseForObject<T>(object: ObjMap<Promise<T>>): Promise<ObjMap<T>> { |
673 | | - const keys = Object.keys(object); |
674 | | - const valuesAndPromises = keys.map(name => object[name]); |
675 | | - return Promise.all(valuesAndPromises).then(values => |
676 | | - values.reduce((resolvedObject, value, i) => { |
677 | | - resolvedObject[keys[i]] = value; |
678 | | - return resolvedObject; |
679 | | - }, Object.create(null)), |
680 | | - ); |
681 | | -} |
682 | | - |
683 | 668 | /** |
684 | 669 | * Implements the logic to compute the key of a given field's entry |
685 | 670 | */ |
@@ -1346,20 +1331,6 @@ export const defaultFieldResolver: GraphQLFieldResolver<any, *> = function( |
1346 | 1331 | } |
1347 | 1332 | }; |
1348 | 1333 |
|
1349 | | -/** |
1350 | | - * Only returns the value if it acts like a Promise, i.e. has a "then" function, |
1351 | | - * otherwise returns void. |
1352 | | - */ |
1353 | | -function getPromise<T>(value: Promise<T> | mixed): Promise<T> | void { |
1354 | | - if ( |
1355 | | - typeof value === 'object' && |
1356 | | - value !== null && |
1357 | | - typeof value.then === 'function' |
1358 | | - ) { |
1359 | | - return (value: any); |
1360 | | - } |
1361 | | -} |
1362 | | - |
1363 | 1334 | /** |
1364 | 1335 | * This method looks up the field on the given type defintion. |
1365 | 1336 | * It has special casing for the two introspection fields, __schema |
|
0 commit comments