Skip to content

Commit 624e6fe

Browse files
lilianammmatosrobrichard
authored andcommitted
add dispatcher class
1 parent 503546b commit 624e6fe

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed

src/type/dispatcher.js

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// @flow strict
2+
3+
import { $$asyncIterator } from 'iterall';
4+
5+
import { type ObjMap } from '../jsutils/ObjMap';
6+
import { type Path, pathToArray } from '../jsutils/Path';
7+
import { type PromiseOrValue } from '../jsutils/PromiseOrValue';
8+
import isPromise from '../jsutils/isPromise';
9+
10+
import { GraphQLError } from '../error/GraphQLError';
11+
12+
export class Dispatcher {
13+
_patches: Array<Promise<{| value: ExecutionPatchResult, done: boolean |}>>;
14+
15+
constructor() {
16+
this._patches = [];
17+
}
18+
19+
execute(
20+
fn: () => PromiseOrValue<ObjMap<mixed>>,
21+
errors: Array<GraphQLError>,
22+
) {
23+
try {
24+
return fn();
25+
} catch (error) {
26+
errors.push(error);
27+
return null;
28+
}
29+
}
30+
31+
add(
32+
label: string,
33+
path: Path | void,
34+
fn: () => PromiseOrValue<ObjMap<mixed>>,
35+
errors: Array<GraphQLError>,
36+
) {
37+
this._patches.push(
38+
Promise.resolve(this.execute(fn, errors)).then(data => {
39+
if (isPromise(data)) {
40+
return data.then(undefined, error => ({
41+
value: {
42+
data: null,
43+
path: pathToArray(path),
44+
label,
45+
errors: [error],
46+
},
47+
done: false,
48+
}));
49+
}
50+
return {
51+
value: {
52+
data,
53+
path: pathToArray(path),
54+
label,
55+
...(errors && errors.length > 0 ? { errors } : {}),
56+
},
57+
done: false,
58+
};
59+
}),
60+
);
61+
}
62+
63+
get(): AsyncIterable<ExecutionPatchResult> | null {
64+
if (this._patches.length === 0) {
65+
return null;
66+
}
67+
const results = this._patches;
68+
69+
function race(promises) {
70+
return new Promise(resolve => {
71+
promises.forEach((promise, index) => {
72+
promise.then(result => {
73+
resolve({ result, index });
74+
});
75+
});
76+
});
77+
}
78+
79+
const getNext = promises => {
80+
if (promises.length === 0) {
81+
return Promise.resolve({ value: undefined, done: true });
82+
}
83+
return race(promises).then(({ result, index }) => {
84+
promises.splice(index, 1);
85+
return result;
86+
});
87+
};
88+
89+
return ({
90+
next() {
91+
return getNext(results);
92+
},
93+
[$$asyncIterator]() {
94+
return this;
95+
},
96+
}: any);
97+
}
98+
}
99+
100+
export type ExecutionPatchResult = {
101+
errors?: $ReadOnlyArray<GraphQLError>,
102+
data?: ObjMap<mixed> | null,
103+
path: $ReadOnlyArray<string | number>,
104+
label: string,
105+
...
106+
};

0 commit comments

Comments
 (0)