From d2f75f6c71ed60986f5fd9721af58d3d6d96a04f Mon Sep 17 00:00:00 2001 From: Matt Sutkowski Date: Mon, 25 Apr 2022 19:53:18 -0700 Subject: [PATCH] Add docs for `timeout` --- docs/rtk-query/api/fetchBaseQuery.mdx | 26 ++++++++++++++++++- packages/toolkit/src/query/fetchBaseQuery.ts | 3 +++ .../src/query/tests/fetchBaseQuery.test.tsx | 4 ++- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/docs/rtk-query/api/fetchBaseQuery.mdx b/docs/rtk-query/api/fetchBaseQuery.mdx index 63d21f5e78..4f150eab03 100644 --- a/docs/rtk-query/api/fetchBaseQuery.mdx +++ b/docs/rtk-query/api/fetchBaseQuery.mdx @@ -13,7 +13,7 @@ description: 'RTK Query > API: fetchBaseQuery reference' This is a very small wrapper around [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) that aims to simplify requests. It is not a full-blown replacement for `axios`, `superagent`, or any other more heavy-weight library, but it will cover the large majority of your needs. -It takes all standard options from fetch's [`RequestInit`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch) interface, as well as `baseUrl`, a `prepareHeaders` function, an optional `fetch` function, and a `paramsSerializer` function. +It takes all standard options from fetch's [`RequestInit`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch) interface, as well as `baseUrl`, a `prepareHeaders` function, an optional `fetch` function, a `paramsSerializer` function, and a `timeout`. - `baseUrl` _(required)_ - Typically a string like `https://api.your-really-great-app.com/v1/`. If you don't provide a `baseUrl`, it defaults to a relative path from where the request is being made. You should most likely _always_ specify this. @@ -38,6 +38,8 @@ It takes all standard options from fetch's [`RequestInit`](https://developer.moz - A function that can be used to apply custom transformations to the data passed into [`params`](#setting-the-query-string). If you don't provide this, `params` will be given directly to `new URLSearchParms()`. With some API integrations, you may need to leverage this to use something like the [`query-string`](https://github.com/sindresorhus/query-string) library to support different array types. - `fetchFn` _(optional)_ - A fetch function that overrides the default on the window. Can be useful in SSR environments where you may need to leverage `isomorphic-fetch` or `cross-fetch`. +- `timeout` _(optional)_ + - A number in milliseconds that represents that maximum time a request can take before timing out. ```ts title="Return types of fetchBaseQuery" no-transpile Promise<{ @@ -114,6 +116,7 @@ There is more behavior that you can define on a per-request basis that extends t - [`body`](#setting-the-body) - [`responseHandler`](#parsing-a-Response) - [`validateStatus`](#handling-non-standard-response-status-codes) +- [`timeout`](#handling-a-custom-timeout) ```ts title="endpoint request options" interface FetchArgs extends RequestInit { @@ -122,6 +125,7 @@ interface FetchArgs extends RequestInit { body?: any responseHandler?: 'json' | 'text' | ((response: Response) => Promise) validateStatus?: (response: Response, body: any) => boolean + timeout?: number } const defaultValidateStatus = (response: Response) => @@ -227,3 +231,23 @@ export const customApi = createApi({ }), }) ``` + +### Adding a custom timeout to requests + +By default, `fetchBaseQuery` has no default timeout value set, meaning your requests will stay pending until your api resolves the request(s) or it reaches the browser's default timeout (normally 5 minutes). Most of the time, this isn't what you'll want. When using `fetchBaseQuery`, you have the ability to set a `timeout` on the `baseQuery` or on individual endpoints. When specifying both options, the endpoint value will take priority. + +```ts title="Setting a timeout value" +import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query' + +export const api = createApi({ + baseQuery: fetchBaseQuery({ baseUrl: '/api/', timeout: 10000 }), // Set a default timeout of 10 seconds + endpoints: (builder) => ({ + getUsers: builder.query({ + query: () => ({ + url: `users`, + timeout: 1000, // We know the users endpoint is _really fast_ because it's always cached. We can assume if its over > 1000ms, something is wrong and we should abort the request. + }), + }), + }), +}) +``` diff --git a/packages/toolkit/src/query/fetchBaseQuery.ts b/packages/toolkit/src/query/fetchBaseQuery.ts index d6443f3e4b..d1e53b1ec9 100644 --- a/packages/toolkit/src/query/fetchBaseQuery.ts +++ b/packages/toolkit/src/query/fetchBaseQuery.ts @@ -173,6 +173,9 @@ export type FetchBaseQueryMeta = { request: Request; response?: Response } * * @param {(params: Record) => string} paramsSerializer * An optional function that can be used to stringify querystring parameters. + * + * @param {number} timeout + * A number in milliseconds that represents that maximum time a request can take before timing out. */ export function fetchBaseQuery({ baseUrl, diff --git a/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx b/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx index ff9debbfd1..0bfb762d1e 100644 --- a/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx +++ b/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx @@ -723,8 +723,10 @@ describe('still throws on completely unexpected errors', () => { expect(req).toBeInstanceOf(Promise) await expect(req).rejects.toBe(error) }) +}) - test('timeout behaviour', async () => { +describe('timeout', () => { + it('throws a timeout error when a request takes longer than specified timeout duration', async () => { jest.useFakeTimers() let result: any server.use(