DEV Community

Pacharapol Withayasakpunt
Pacharapol Withayasakpunt

Posted on

Is fetch too low-level? Do you have a favorite wrapper?

Furthermore, I am not sure about node-fetch or isomorphic-fetch, on Node.js's side.

What is surprising about fetch, is that it does not "raise-for-status" by default. Similarly, not sure about XMLHTTPRequest, where I rarely use it natively. See XMLHTTPRequest vs fetch.

Maybe a relatively safe way is to do it like this.

import deepMerge from './util'

export function createApi<
  T extends Record<
      options: RequestInit
      response: any
  validate = (r) => {
    if (!r.ok) throw new Error(`${r.status}: ${r.statusText}`)
  parse = (r) => r.json(),
  options = {},
}: {
  validate?: (r: Response) => void
  parse?: (r: Response) => Promise<any>
  options?: RequestInit
} = {}) {
  return async <K extends keyof T>(
    url: K,
    opts: T[K]['options'] = {}
  ): Promise<T[K]['response']> => {
    return fetch(url as string, deepMerge(options, opts)).then(async (r) => {
      return parse(r)
        .then((r) => {
          if (r.error) throw new Error(r.error)
          return r
Enter fullscreen mode Exit fullscreen mode

Umm, I tried writing it, and it gets a little complex in TypeScript version...

Yes, this is not even accounting for AbortController...

Discussion (4)

rolfstreefkerk profile image
Rolf Streefkerk

Request is what I use, but that has been deprecated.

The Request team recommends either one from this list

tomdohnal profile image
Tom Dohnal

axios library is a common choice. It's a very small library for making requests. I find it's API a bit friendlier that native fetch

patarapolw profile image
Pacharapol Withayasakpunt Author

I actually resorted to ky. I would probably also use ky-universal or got, if I need to.

llldar profile image

fetch is just fine, I would prefer 'cross-fetch' for isomorphic use of fetch between frontend and node.js