-
Notifications
You must be signed in to change notification settings - Fork 311
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Is there a convenient way to use graphql-request with an AbortController? #182
Comments
You can pass options to the
|
i actually have some thoughts on this. we're doing this ourselves, and ran into a few really annoying issues. we patched a workaround but i think there could be an API change to the problem(also see mysticatea/abort-controller#25) when you create if you create a brand new once an so once it's triggered, every subsequent fetch that uses this same instance of my hacky patchI've created a fork of I then defined a import AbortController from 'botany-abort-controller';
const signalMap = new WeakMap();
export const getTimeoutSignal = timeout => {
if (!Number.isInteger(timeout)) {
throw new TypeError(`Expected an integer, got ${typeof timeout}`);
}
const controller = new AbortController();
const timeoutId = setTimeout(() => {
controller.abort();
}, timeout);
signalMap.set(controller.signal, timeoutId);
return controller;
};
export const resetTimeout = (controller, timeout) => {
const signal = controller.signal;
controller.reset(signal);
clearTimeout(signalMap.get(signal));
const timeoutId = setTimeout(() => {
controller.abort();
}, timeout);
signalMap.set(controller.signal, timeoutId);
}; here's what usage looks like: // graphql client
const client = (
timeout: AbortController,
headers: Record<string, string> = {}
) =>
new GraphQLClient(process.env.GRAPHQL_URL, {
signal: timeout.signal,
});
// polly-js policy
const withRetries: (
controller: AbortController
) => SdkFunctionWrapper = controller => <T>(
action: () => Promise<T>,
operationName: string
) =>
polly()
.handle((err: Error) => {
if (
/AbortError/.exec(err.name) ||
err.message.includes('connect ETIMEDOUT') ||
err.message.includes('network timeout') ||
err.message.includes('write EPIPE')
) {
warn('GraphqlClient:NetworkError', err, { operationName });
return true;
}
error('GraphqlClient:NonTimeoutError', err, { operationName });
return false;
})
.waitAndRetry([200, 400, 800])
.executeForPromise(info => {
if (info.count === 3) {
error('GraphqlClient:MaxRetries', {
...info,
operationName,
});
}
/* HERE IS WHERE YOU RESET THE ABORTED SIGNAL ========= */
// reset timeout signal BEFORE executing the call. otherwise, timer
// will be started before the `waitAndRetry` backoff times
resetTimeout(controller, TIMEOUT_MS);
/* HERE IS WHERE YOU RESET THE ABORTED SIGNAL ========= */
return withClientTiming(action, operationName);
});
// getting a client
const getGraphqlClient = () => {
const timeout = getTimeoutSignal(TIMEOUT_MS);
return getSdk(client(timeout), withRetries(timeout));
}; less hacky solutions
|
|
Yes, I agree with option 2. 👍 Before switching to There's also |
an out of the box retry/timeout mechanism is for me to be the main thing that is lacking compared to the apollo-client library |
Please, can we pass fetch options per request, not just on client creation??? |
Just wondering if there was any news / updates on this. Just found myself running into the same problem. |
Just push this PR #303 to support a |
Closed by #303 Thanks @arnaudbzn ! |
Is there a convenient way to use graphql-request with an AbortController?
I would like to debounce and cancel in-flight requests when they are repeated.
The text was updated successfully, but these errors were encountered: