⏱ Synchronous wrapper around the fetch()
API
🖥️ Works in Node.js and the browser
👨🏭 Works great in web Worker
threads!
⚛️ Perfect for WebAssembly
💻 Works in the browser using XMLHttpRequest
fetch()
API. This is a niche package.
You can use this with both Node.js and the browser! If you're using a bundler like Vite or webpack, you can install it using npm. If you're importing it live in your browser, you can use an npm CDN like ESM>CDN or jsDelivr.
npm install sync-fetch
import {} from "https://esm.sh/@jcbhmr/fetch-sync";
🛑 It is not recommended to use this in a browser on the main UI thread!
fetchSync()
is great for Worker
threads, but you don't want to block your
user's click events in the UI.
The API surface is mostly a mirror of the Fetch Standard, just with non-async things in-place of normally async operations:
- All
Promise<T>
-returning functions (.text()
,.json()
,.blob()
, etc.) are replaced with synchronous versions. These all return the values immediately. - The
.body
value has been replaced with anIterableIterator<Uint8Array>
instead of the normalReadableStream<Uint8Array>
. We use this instead of anArray
to better parallel theReadableStream
's interface style. Use.next()
or a for-of loop to read it chunk-by-chunk.
import { fetchSync, RequestSync, ResponseSync } from "@jcbhmr/fetch-sync";
const requestSync = new RequestSync("https://httpbin.org/post", {
method: "POST",
headers: {
"Content-Type": "text/plain",
},
body: "Hello world!",
});
const responseSync = fetchSync(requestSync);
console.log(responseSync.status);
//=> 200
console.log(responseSync.bodyUsed);
//=> false
// Remember! This is an IterableIterator<Uint8Array> now.
const chunks = [...responseSync.body];
console.log(chunks);
//=> [ Uint8Array [ ... ], Uint8Array [ ... ] ]
console.log(responseSync.bodyUsed);
//=> true
Due to the fact that the API surface must be almost completely synchronous,
there are a few things that are supported by the normal native fetch()
function that we cannot support. Those are:
ReadableStream
instances asbody
parameters. There's no easy way to read them synchronously.Blob
instances asbody
parameters. Same asReadableStream
, their async nature makes them impossible to reconcile with this.- Proprietary Node.js-specific options to the
fetchSync()
function. Things like Node Fetch'sagent
property are not implemented here. AbortSignal
instances for cancellation. EvenXMLHttpRequest
doesn't let you set atimeout
for synchronous requests. Any providedAbortSignal
will throw an error only if it has already been aborted. They don't work to cancel mid-flight requests since there's no way you would even be able to.abort()
one while the thread is blocked.- The
.formData()
function to get a parsedFormData
object. This isn't implemented yet. - Proper binary responses in the main thread in the browser. When using
synchronous XHR, we cannt set the
.responseType
option to"arraybuffer"
, so we have to derive the bytes from the default text-based response usingTextEncoder
. This may not be 100% accurate. RequestSync
andResponseSync
are not interoperable with the nativeRequest
andResponse
classes. They are two completely separate "chains" with independant backing APIs.
These limitations are unlikely to be a problem for most users. If you're really
interested in what options the RequestSync
and ResponseSync
classes support
for options, you can check the (relatively) simple implementation files to see
how they work. More developer information can be found on the dev wiki.