- Introduction
- Getting started
- Philosophy
- Comparison
- Limitations
- Debugging runbook
- FAQ
- Basics
- Concepts
- Network behavior
- Integrations
- API
- CLI
- Best practices
- Recipes
- Cookies
- Query parameters
- Response patching
- Polling
- Streaming
- Network errors
- File uploads
- Responding with binary
- Custom worker script location
- Global response delay
- GraphQL query batching
- Higher-order resolver
- Keeping mocks in sync
- Merging Service Workers
- Mock GraphQL schema
- Using CDN
- Using custom "homepage" property
- Using local HTTPS
Global response delay
Delay all responses in the application.
While you can control the response time (i.e. delay) of individual responses using the delay()
API, sometimes you want to apply a delay consistently to all mocked responses. There are a couple of ways you can do that with MSW.
Option 1: A delay passthrough handler
The request handlers you define are executed in order, which means that a single intercepted request can execute multiple request handlers (until there’s one that returns a mocked response).
You can take advantage of that execution order and introduce a passthrough request handler that matches all outgoing requests and adds a delay in its response resolver without returning a mocked response.
import { http, delay, HttpResponse } from 'msw'
export const handlers = [
http.all('*', async () => {
await delay(1000)
}),
http.get('/user', () => {
return HttpResponse.json({ id: 'abc-123' })
}),
http.post('/cart/:cartId', () => {
return new HttpResponse(null, { status: 201 })
}),
]
In the example above, both GET /user
and POST /cart/:cartId
requests will match the http.all('*')
request handler, which will delay their eventual resolution by 1000ms.
This option provides you with a consistent delay across all request handlers but makes it harder to opt-out from this behavior for specific handlers (you’d have to put those before the all-matching http.all('*')
).
Option 2: Higher-order response resolver
You can create a higher-order response resolver that encapsulates the delay logic while giving you the flexibility over which responses to delay.
// withDelay.ts
import { delay, HttpResponseResolver } from 'msw'
export async function withDelay(resolver: HttpResponseResolver): HttpResponseResolver {
return async (...args) => {
await delay(1000)
return resolver(...args)
}
}
You can design the
withDelay()
function as you wish. For example, instead of hard-coding the delay duration, you can expose it as an argument to thewithDelay()
function for each individual request handler to specify.
// handlers.ts
import { http, HttpResponse } from 'msw'
import { withDelay } from './withDelay'
export const handlers = [
http.get('/user', withDelay(({ request }) => {
return HttpResponse.json({ id: 'abc-123' })
}),
http.post('/cart/:cartId', withDelay(({ request }) => {
return new HttpResponse(null, { status: 201 })
}),
http.get('/products', () => {
return HttpResponse.json([1, 2, 3])
})
]
In the example above, the GET /user
and POST /cart/:cartId
requests will be delayed by 1000ms because their response resolvers are wrapped in the withDelay()
higher-order resolver. Note that the GET /products
request will no have any delay, respectively.
This option gives you more control over which responses to delay while encapsulating the delay logic within the higher-order response resolver for consistency.
Learn more about creating higher-order response resolvers:
Higher order resolver
Perform an additional request outside of the interception algorithm.