From 912c2e5ee6cb1ef04c887df6d1078ff895231696 Mon Sep 17 00:00:00 2001 From: Szymon Marczak <36894700+szmarczak@users.noreply.github.com> Date: Sat, 14 Dec 2019 22:29:40 +0100 Subject: [PATCH] Emit timeout errors as soon as possible Fixes #997 --- source/utils/timed-out.ts | 11 +---------- test/timeout.ts | 14 +++++++++++++- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/source/utils/timed-out.ts b/source/utils/timed-out.ts index 68cae7109..3406e8d80 100644 --- a/source/utils/timed-out.ts +++ b/source/utils/timed-out.ts @@ -33,21 +33,12 @@ export default (request: ClientRequest, delays: Delays, options: TimedOutOptions const {once, unhandleAll} = unhandler(); const addTimeout = (delay: number, callback: (delay: number, ...args: T) => void, ...args: T): (typeof noop) => { - // Event loop order is timers, poll, immediates. - // The timed event may emit during the current tick poll phase, so - // defer calling the handler until the poll phase completes. - let immediate: NodeJS.Immediate; - const timeout: NodeJS.Timeout = setTimeout(() => { - // @ts-ignore https://github.com/microsoft/TypeScript/issues/26113 - immediate = setImmediate(callback, delay, ...args); - immediate.unref?.(); - }, delay); + const timeout = setTimeout(callback, delay, ...args) as unknown as NodeJS.Timeout; timeout.unref?.(); const cancel = (): void => { clearTimeout(timeout); - clearImmediate(immediate); }; cancelers.push(cancel); diff --git a/test/timeout.ts b/test/timeout.ts index 2ffa66d31..1bac1cdc6 100644 --- a/test/timeout.ts +++ b/test/timeout.ts @@ -10,7 +10,7 @@ import delay = require('delay'); import CacheableLookup from 'cacheable-lookup'; import {Handler} from 'express'; import pEvent = require('p-event'); -import got from '../source'; +import got, {TimeoutError} from '../source'; import timedOut from '../source/utils/timed-out'; import slowDataStream from './helpers/slow-data-stream'; import {GlobalClock} from './helpers/types'; @@ -622,3 +622,15 @@ test.serial('cancelling the request removes timeouts', withServer, async (t, ser await delay(1000); }); + +test('timeouts are emitted ASAP', async t => { + const timeout = 500; + const marginOfError = 100; + + const error: TimeoutError = await t.throwsAsync(got('http://192.0.2.1/test', { + retry: 0, + timeout + }), TimeoutError); + + t.true(error.timings.phases.total! < (timeout + marginOfError)); +});