Expo Go client and Metro bundler: Propagation of developer‑defined fetch timeouts
0 reputation · 18 Oct 2023, 12:07 UTC
0 reputation · 18 Oct 2023, 12:07 UTC
Expo’s managed workflow wraps fetch/XMLHttpRequest calls and forwards AbortController signals to the native HTTP stack, but the documentation does not state whether a developer‑specified timeout value (e.g., fetch(url, { timeout: 5000 }) or a timeout polyfill) is honored when the request runs through Expo Go.
The underlying native stack may apply its own default (≈30 s) or the OTA update mechanism’s hard‑coded timeout, creating uncertainty about the actual limit enforced and whether timeout‑related errors can be distinguished from explicit aborts.
Does Expo’s managed workflow respect custom timeout values set on fetch requests? If they are ignored, what timeout is actually applied? Is there a way to configure or override the internal timeout used by Expo’s networking layer?
35775 reputation · 18 Oct 2023, 17:31 UTC
No. Expo Go and the Expo managed workflow do not honor a developer-specified timeout init option on fetch. The standard Web Fetch API has no timeout member. Passing fetch(url, { timeout: 5000 }) is non-standard and is silently ignored by React Native and Expo runtimes. It is not propagated to the native HTTP stack.
A timeout you define yourself is honored only when you implement it with the standard AbortController signal.
AbortController.signal to the native layer.The Expo managed workflow does not expose a global fetch configuration. Effective timeout limits are determined by the underlying native stacks and OS conditions, which vary across SDK versions and platforms. Metro bundler only handles JavaScript bundling and does not affect runtime networking timeouts.
To enforce a custom timeout in Expo Go, you must use the AbortController API combined with setTimeout:
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 5000);
try {
const response = await fetch('https://api.example.com/data', {
signal: controller.signal
});
const data = await response.json();n} catch (error) {
if (error.name === 'AbortError') {
console.log('Fetch timed out');
} else {
console.log('Network error', error);
}
} finally {
clearTimeout(timeout);
}Note: Timeout-related errors from AbortController are distinct from generic network errors, but error messages can be similar. Always inspect the error.name to distinguish between an explicit abort and a transport failure.
Use comments to ask for clarification. Post a solution as an answer.
35,775 reputation · 18 Oct 2023, 22:02 UTC
In Expo Go the timeout field you sometimes see in fetch(url, {timeout:…}) is ignored because the native networking stack (NSURLSession on iOS, OkHttp on Android) does not expose a standard fetch timeout. The stack applies its own socket/read timeout—roughly 30 seconds on most devices—and Metro has no role in that timing.
To guarantee a consistent deadline you should wrap fetch with an AbortController and a setTimeout that calls abort() when the desired time expires. The abort signal is forwarded to the native request, so the rejection can be distinguished from a network‑level timeout.