⏱ Add delay to a request in ExpressJS
I was working on a Next.js app with a custom server, which had an issue around the loading state for a dynamically imported component.
For the uninitiated, a dynamically imported component is split into its own file (or a chunk) and loaded on-demand. This helps in reducing the initial load time of the app, by not loading all the components at the start.
In Next.js, it looks like this:
const component = dynamic(() => import('@/component/SearchEngine'), {
loading: Loader,
})
Problem was, my internet was too fast to simulate the issue locally. Never heard of fast internet being a problem, right? The Loader
was only shown for a very short time, and then disappeared. I needed the loader to show for a longer time, to replicate the issue.
I used the throttling options in dev tools, but that was throttling the entire page and all the requests. It was not a pleasant experience to debug.
So I implemented a middleware that delays the response to a particular request only. This is a very simple middleware, but it works for my use case.
const REQUEST_DELAY = 2000
const RESPONSE_DELAY = 5000
const delayResponse = (req, res, next) => {
if (THROTTLE_PATHS(req.url)) {
// Delay request by 2 seconds
setTimeout(next, REQUEST_DELAY)
// Delay response completion by 5 seconds
const endOriginal = res.end
res.end = (...args) => {
setTimeout(() => {
endOriginal.apply(res, args)
}, RESPONSE_DELAY)
}
} else {
next()
}
}
I have two setTimeout
calls in the middleware. The first one is to delay processing the request by 2 seconds. The second one is to delay the response completion by 5 seconds.
THROTTLE_PATHS
is a method that has list of URL paths that needs a delayed response.
THROTTLE_PATHS
is a very fancy implementation for my use-case. You can get away with a simple if
statement.
Adding the middleware is as simple as: app.use(delayResponse)
.
And that's it! I was able to see the Loader
for a longer time, and debugging was a lot easier.