npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@superutils/fetch

v1.0.1

Published

A lightweight `fetch` wrapper for browsers and Node.js, designed to simplify data fetching and reduce boilerplate.

Downloads

244

Readme

@superutils/fetch

A lightweight fetch wrapper for browsers and Node.js, designed to simplify data fetching and reduce boilerplate.

This package enhances the native fetch API by providing a streamlined interface and integrating practical & useful features from @superutils/promise. It offers built-in support for automatic retries, request timeouts, interceptors, and effortless request cancellation, making complex asynchronous flows simple and manageable.

Table of Contents

Features

  • Simplified API: Automatically parses JSON responses, eliminating the need for .then(res => res.json()).
  • Built-in Retries: Automatic request retries with configurable exponential or fixed backoff strategies.
  • Request Timeouts: Easily specify a timeout for any request to prevent it from hanging indefinitely.
  • Cancellable & Debounced Requests: The fetchDeferred utility provides debouncing and throttling capabilities, automatically cancelling stale or intermediate requests. This is ideal for features like live search inputs.
  • Interceptors: Hook into the request/response lifecycle to globally modify requests, handle responses, or manage errors.
  • Strongly Typed: Written in TypeScript for excellent autocompletion and type safety.
  • Isomorphic: Works seamlessly in both Node.js and browser environments.

Installation

npm install @superutils/fetch

Usage

fetch(url, options)

Make a simple GET request. No need for response.json() or result.data.theActualData drilling.

import fetch from '@superutils/fetch'

const theActualData = await fetch('https://dummyjson.com/products/1', {
	method: 'get', // default
})
console.log(theActualData)
// Alternative:
const theActualData = await fetch.get('https://dummyjson.com/products/1')
console.log(theActualData)

Method Specific Functions

While fetch() provides access to all HTTP request methods by specifying it in options (eg: { method: 'get' }), for ease of use you can also use the following:

  • fetch.delete(...)
  • fetch.get(...)
  • fetch.head(...)
  • fetch.options(...)
  • fetch.patch(...)
  • fetch.post(...)
  • fetch.put(...)

Deferred variants: To debounce/throttle requests.

  • fetch.delete.deferred(...)
  • fetch.get.deferred(...)
  • fetch.head.deferred(...)
  • fetch.options.deferred(...)
  • fetch.patch.deferred(...)
  • fetch.post.deferred(...)
  • fetch.put.deferred(...)

fetch.get.deferred(deferOptions, defaultUrl, defaultOptions)

A practical utility that combines PromisE.deferred() from the @superutils/promise package with fetch(). It's perfect for implementing cancellable, debounced, or throttled search inputs.

import fetch, { fetchDeferred, ResolveIgnored } from '@superutils/fetch'

// Create a debounced search function with a 300ms delay.
const searchProducts = fetch.get.deferred({
	delayMs: 300, // Debounce delay
	resolveIgnored: ResolveIgnored.WITH_UNDEFINED, // Ignored (aborted) promises will resolve with `undefined`
})

// User types 'iphone'
searchProducts('https://dummyjson.com/products/search?q=iphone').then(
	result => {
		console.log('Result for "iphone":', result)
	},
)

// Before 300ms has passed, the user continues typing 'iphone 9'
setTimeout(() => {
	searchProducts('https://dummyjson.com/products/search?q=iphone 9').then(
		result => {
			console.log('Result for "iphone 9":', result)
		},
	)
}, 200)
// Outcome:
// The first request for "iphone" is aborted.
// The first promise resolves with `undefined`.
// The second request for "iphone 9" is executed after the 300ms debounce delay.

Behavior with different deferOptions in the example above:

  • throttle: true: Switches from debounce to throttle mode. The first request for "iphone" would execute immediately. The second request for "iphone 9", made within the 300ms throttle window, would be ignored.
  • delayMs: 0: Disables debouncing and throttling, enabling sequential/queue mode. Both requests ("iphone" and "iphone 9") would execute, but one after the other, never simultaneously.
  • resolveIgnored: Controls how the promise for an aborted request (like the first "iphone" call) resolves.
    1. ResolveIgnored.WITH_UNDEFINED (used in the example): The promise for the aborted "iphone" request resolves with undefined.
    2. ResolveIgnored.WITH_LAST: The promise for the aborted "iphone" request waits and resolves with the result of the final "iphone 9" request. Both promises resolve to the same value.
    3. ResolveIgnored.NEVER: The promise for the aborted "iphone" request is neither resolved nor rejected. It will remain pending indefinitely.
    4. ResolveIgnored.WITH_ERROR: The promise for the aborted "iphone" request is rejected with a FetchError.

Using defaults to reduce redundancy

import fetch, { ResolveIgnored } from '@superutils/fetch'

// Create a throttled function to fetch a random quote.
// The URL and a 3-second timeout are set as defaults, creating a reusable client.
const getRandomQuote = fetch.get.deferred(
	{
		delayMs: 300, // Throttle window
		throttle: true,
		// Ignored calls will resolve with the result of the last successful call.
		resolveIgnored: ResolveIgnored.WITH_LAST,
	},
	'https://dummyjson.com/quotes/random', // Default URL
	{ timeout: 3000 }, // Default fetch options
)

// Call the function multiple times in quick succession.
getRandomQuote().then(quote => console.log('Call 1 resolved:', quote.id))
getRandomQuote().then(quote => console.log('Call 2 resolved:', quote.id))
getRandomQuote().then(quote => console.log('Call 3 resolved:', quote.id))

// Outcome:
// Due to throttling, only one network request is made.
// Because `resolveIgnored` is `WITH_LAST`, all three promises resolve with the same quote.
// The promises for the two ignored calls resolve as soon as the first successful call resolves.
// Console output will show the same quote ID for all three calls.

fetch.post(url, options)

fetch.post.deferred(deferOptions, url, postOptions)