sindresorhus / ky

🌳 Tiny & elegant JavaScript HTTP client based on the Fetch API
MIT License
13.62k stars 363 forks source link

Add retry.delay option to control the time between retries #533

Closed rclarey closed 11 months ago

rclarey commented 1 year ago

Related to option (2) to #509

Changes

rclarey commented 1 year ago

@sindresorhus @szmarczak @sholladay Sorry, can you please take a look when you have a chance

sindresorhus commented 11 months ago

You need to document it in the readme too.

TommySorensen commented 10 months ago

FYI: @sindresorhus After the changes in this PR, then i'm seeing warnings in NextJS like this on all my endpoints.

 âš  fetch for https://myspeficisomeurl.com on /cart specified "cache: default" and "revalidate: 60", only one should be specified.

I'm using ky pretty much basic. But it seems like that KY internally is adding the cache to the fetcher with value of default.

const contentApi = ky.create({
  prefixUrl: `${process.env.CONTENT_API_URL}/api`,
  retry: 0,
});

contentApi
    .get(`getSomething/${someId}`, {
      next: { revalidate: 60 },
    })
    .json();
rclarey commented 10 months ago

@TommySorensen this is because Ky internally constructs a Request, and the browser will automatically set request.cache to "default" if it's not specified. Screenshot 2023-12-04 at 10 07 50 So this is an issue with Next's warning rather than an issue with Ky.

I just checked and it seems this was fixed in Next.js in https://github.com/vercel/next.js/pull/58505, and released in https://github.com/vercel/next.js/releases/tag/v14.0.3

BTW if like me you're not using Next 14 yet, this is a workaround I've been using:

function fetchWith(override: RequestInit): typeof fetch {
  return (input, init) => {
    if (input instanceof Request) {
      return fetch(input.url, {
        // Copy all properties *except* for `cache` to prevent Next from warning that
        // we pass both `cache` and `revalidate`.
        // This happens because Ky internally constructs a `Request` object, so `cache`
        // will always be the set to `"default"` even when we don't explicitly set it.
        body: input.body,
        credentials: input.credentials,
        headers: input.headers,
        integrity: input.integrity,
        keepalive: input.keepalive,
        method: input.method,
        mode: input.mode,
        redirect: input.redirect,
        referrer: input.referrer,
        referrerPolicy: input.referrerPolicy,
        signal: input.signal,
        ...init,
        ...override,
      });
    }
    return fetch(input, { ...init, ...override });
  };
}

// then use it like
contentApi
  .get(`getSomething/${someId}`, {
    fetch: fetchWith({ next: { revalidate: 60 } }),
  })
  .json();