-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
No ability to set a Timeout behaviour #4122
Comments
Currently trying this code to implement a 1 millisecond timeout. I expect all requests to be cancelled, but I can see responses are still being received successfully, AFTER the cancel request is called. Is this because the code is expecting the const fetchRequest = new ethers.FetchRequest(network)
const timeoutMS = 1
fetchRequest.preflightFunc = async (req: ethers.FetchRequest): Promise<ethers.FetchRequest> => {
;(req as any).timeoutRef = setTimeout(() => {
try {
req.cancel()
} catch (error) {
console.error(`Cancelled request after ${timeoutMS.toLocaleString()} milliseconds`)
}
}, timeoutMS)
return req
}
// intercept the response
fetchRequest.processFunc = async (
req: ethers.FetchRequest,
resp: ethers.FetchResponse
): Promise<ethers.FetchResponse> => {
if ((req as any).timeoutRef) {
clearTimeout((req as any).timeoutRef)
}
// ... the response still comes through successfully, and is handed back to waiting promise, despite a 1 millisecond timeout
return resp
} |
The Signalling was added as a stub to add in the future. I can look at this now. Each platform has its own support for cancelling requests, and some are actually honoured (i.e. stop the request and reclaim socket resources) while some simply discard the results when they finally arrive. It will still be up to the platform to decide how to handle this, but at the very least, Ethers should provide a standard and consistent experience. |
I needed the same thing with contract function calls. It's not just about cancelling requests after a specific timeout but it's also useful for cleanups in frontend. I saw some signal implementations for request cancellation but seems like they're for internal usages. It'd be nice if we get a similar usage like |
I had a lot of ideas I tried out for v6, but it’s hard because of the way TypeScript and Promises work together. But I have some ideas for v7 to try out, which will be that each provider method (and Contract overrides) will accept an AbortController, as well as a customData, which can be included in all errors emitted and more importantly in the getUrlFunc so additional data can be passed into custom fetching. Any other ideas for options to pass in? |
No need to pass all const abortController = new AbortController()
// which would internally listen for `signal.addEventListener('abort', () => ...)` and cancel the requests
contract.func(...args, { signal: abortController.signal })
setTimeout(() => abortController.abort(), 3000) // abort after 3 seconds Same for unmounts in frontend, React for example: useEffect(() => {
const abortController = new AbortController()
// which would internally listen for `signal.addEventListener('abort', () => ...)` and cancel the requests
contract.func(...args, { signal: abortController.signal })
return () => abortController.abort() // abort if component is unmounted
}, []) |
Oh, sorry. Yes, that’s what I meant. There is an Ethers object for that, so that the interface is the same between platforms. :) |
There is a bug in request.setTimeout(timeout, function() {
request.abort();
}); |
@andkom Hey, do you also have endless requests sometimes? |
@bytesbay yes, but not fixed with the code above |
Is this timeout feature not implemented yet on v6? Is it planned for v7 |
This is still planned for v6. :) |
I've added some logic to handle timeout and cancel in FetchRequest consistently between the browser and Node. I'd love an extra set of eyes on it. I can also get a beta build published on npm if there is interest. |
This has been published in v6.13.0. Thanks! :) |
Ethers Version
6.4.1
Search Terms
cancel, abort signal, https agent
Describe the Problem
I cannot find a way to cancel a Json RPC request inflight, with the v6 library (specifically to set a timeout).
All the methods I've tried, appear not to work, and I can't see anything in the documentation.
Attempt #1 (Bug)
Attempt: Set the
timeout
field to1
(ms) on theFetchRequest
.Expected: requests to cancel effectively immediately.
Result: Requests still complete successfully after a duration of approx half a second.
Attempt #2 (Bug)
Attempt: Call the
FetchRequest.cancel()
function.Expected: requests to cancel mid flight
Result: request throws error "request has not been sent" (I have a long request, I'd expect it to at least have been initialised after 50ms)
Attempt 3 (Feature request)
Attempt: Supply an AbortSignal or FetchCancelSignal in the
preflightFunc
Expected: ability to set a custom abort signal
Result: there is no documented or visible way to set an abort signal
Note: Additionally,
#signals
are not copied during theclone()
function.Attempt 4 (Feature request)
Attempt: Supply a custom Https Agent
Expected: most libraries provide the ability to override or set the underlying Https Agent (e.g. in v5)
Result: this is no longer supported
Code Snippet
Contract ABI
Errors
No response
Environment
node.js (v12 or newer)
Environment (Other)
Node: v18.3.0
The text was updated successfully, but these errors were encountered: