ky
Version:
Tiny and elegant HTTP client based on the Fetch API
31 lines • 1.39 kB
JavaScript
import { TimeoutError } from '../errors/TimeoutError.js';
import { cancelBody } from './body.js';
// `Promise.race()` workaround (#91)
export default async function timeout(request, init, abortController, options) {
let timeoutId;
let timedOut = false;
try {
return await new Promise((resolve, reject) => {
timeoutId = setTimeout(() => {
timedOut = true;
abortController?.abort();
reject(new TimeoutError(request));
}, options.timeout);
// Called unbound so a native `window.fetch` is not invoked with `options` as `this`, which throws "Illegal invocation" in browsers.
// A synchronous throw rejects the promise, and `finally` still clears the timer so it cannot abort a later retry attempt.
const { fetch } = options;
fetch(request, init).then(response => {
// A response arriving after the timeout already won is discarded, so its unused body is cancelled. Fire-and-forget: cancellation failures are ignored and never delay the rejection.
if (timedOut) {
cancelBody(response);
return;
}
resolve(response);
}).catch(reject);
});
}
finally {
clearTimeout(timeoutId);
}
}
//# sourceMappingURL=timeout.js.map