graphql-request icon indicating copy to clipboard operation
graphql-request copied to clipboard

How can I set http timeout for GraphQLClient rawRequest?

Open egacl-agilesoft opened this issue 4 years ago • 5 comments

Hi!

I need your help to know How can I set http timeout for GraphQLClient rawRequest? I was read the documentation but I didn't found anything about.

Thanks

egacl-agilesoft avatar Nov 06 '20 00:11 egacl-agilesoft

I found into source code RequestInit object that contains a timeout attribute. These param can set into GraphQLClient constructor.

egacl-agilesoft avatar Nov 06 '20 01:11 egacl-agilesoft

I did install "2.1.0-next.1" version with NPM. In this version RequestInit doesn't have "timeout" attribute. How can I set http timeout with this version?

egacl-agilesoft avatar Nov 06 '20 01:11 egacl-agilesoft

Hi!

I checked the repository for usages of the timeout, and it seems this option along with others are just transferred to CrossFetch. As far as I can see CrossFetch does not support timeout.

So, it seems there is no support of the timeout in neither of the versions. Is it something that is under development?

Thanks

maximvsidorenko avatar May 14 '21 13:05 maximvsidorenko

I got client stuck on request today, and thanks @maximvsidorenko your work did save my time to find how to setup timeout. The cross-fetch is a proxy to the node-fetch and the github fetch (issue: https://github.com/lquixada/cross-fetch/issues/62).

And both of these libraries can setup timeout in this way:

import AbortController from 'abort-controller'

const controller = new AbortController()
const timeoutID = setTimeout(() => {
	controller.abort();
}, 150)

try {
  const response = await crossFetch('https://example.com', {signal: controller.signal})
  const data = await response.json()
} catch (error) {
  if (error instanceof crossFetch.AbortError) {
    console.log('request was aborted')
  }
} finally {
  clearTimeout(timeoutID)
}

So you can setup timeout in Graph Client:

import { GraphQLClient, gql } from 'graphql-request'
import AbortController from 'abort-controller'

const controller = new AbortController();
const timeoutId = setTimeout(() => {
  controller.abort()
  console.log('timeout')
}, 10)
const graphClient = new GraphQLClient(url, {
  signal: controller.signal
})

// request
await graphClient.request(query, variables)

// rawRequest
graphClient.rawRequest(query, variables)

Didn't add try catch in last piece of code, sorry for that. Hope it helps.

sc0Vu avatar May 31 '21 14:05 sc0Vu

I used the following: const req = (route, query, variables, timeout) => new Promise((resolve, reject) => { const to = setTimeout(() => { reject({ data: {}, status: 408, error: 'Timeout' }); }, timeout); request(route, query, variables).then((data) => { resolve({ data, status: 200 }); }).finally(() => { clearTimeout(to); }).catch((error) => { reject({ data: {}, status: 500, error }); }); });

yairnizfiv avatar Jan 18 '22 14:01 yairnizfiv

Note about the above solution; you'll need to clear that timeout or abort would still be called. A try/finally would work.

There's also an example of how to do this in examples/request-cancellation.ts that doesn't rely on another npm module, using the native AbortController.

https://github.com/jasonkuhrt/graphql-request/blob/6b3396bbd4c3b678f84abe8bcf697a26e563721c/examples/request-cancellation.ts

w33ble avatar Nov 14 '23 22:11 w33ble