Response Iterator
response-iterator is a utility library designed to normalize various HTTP response bodies into a consistent asynchronous iterator interface, compatible across both browser and Node.js environments. It currently stands at stable version 1.0.10 and is regularly maintained. The library abstracts away the differences in how `Response` objects (or similar constructs) are handled by different HTTP clients such as standard `fetch`, `node-fetch`, `cross-fetch`, `axios`, `got`, and `undici`. Its key differentiator is providing a simple `for await...of` loop mechanism to consume streamed data chunks, making it easier to process large responses efficiently without loading the entire body into memory, irrespective of the underlying fetch implementation. It significantly simplifies working with streaming data by adhering to the `Symbol.asyncIterator` protocol.
Common errors
-
TypeError [ERR_REQUIRE_ESM]: require() of ES Module .../node_modules/response-iterator/dist/index.js from ... not supported.
cause Attempting to import `response-iterator` using `require()` in a CommonJS environment, but the package is ESM-only.fixChange `const responseIterator = require('response-iterator');` to `import responseIterator from 'response-iterator';`. Ensure your project's `package.json` has `"type": "module"` or use dynamic imports like `const responseIterator = (await import('response-iterator')).default;`. -
TypeError: responseIterator is not a function
cause This usually happens if `responseIterator` is imported incorrectly, or if the module itself failed to load or initialize. It could also mean `responseIterator` was imported as a named import when it's a default export.fixVerify the import statement is `import responseIterator from 'response-iterator';` (for a default export). If in CommonJS, confirm dynamic import usage: `const responseIterator = (await import('response-iterator')).default;`. -
TypeError: (intermediate value).then is not a function
cause This error occurs when `await` is used on a non-Promise value, or when an `async` function tries to iterate over an async iterable without `for await...of` in an `async` context, or a synchronous iterable is treated as async.fixEnsure the function containing `for await (const chunk of responseIterator(res))` is declared `async`. Also, verify that `responseIterator(res)` is indeed returning an async iterable and not a plain value or a Promise of a value that needs further resolution.
Warnings
- breaking Major version 1.0.0 introduces breaking changes. While specific release notes for 0.x to 1.x are not readily available, according to semantic versioning, a jump to `1.0.0` signifies that the API is now considered stable, but with potential breaking changes from any `0.x` version. Always review your usage when upgrading from `0.x` to `1.x`.
- breaking The package transitioned to an ESM-only distribution model with its `1.x` release. Attempting to `require()` this package in a CommonJS module will fail.
- gotcha Asynchronous iterators, including those produced by `response-iterator`, must be consumed within an `async` function using a `for await...of` loop. Forgetting `await` or not being in an `async` context will lead to runtime errors or unhandled promises.
- gotcha When handling network responses, especially large streams, it's crucial to properly handle errors that might occur during the stream's lifetime. An unhandled exception in the underlying `Response` stream or during chunk processing can cause the consuming `for await...of` loop to hang or terminate unexpectedly without proper cleanup.
Install
-
npm install response-iterator -
yarn add response-iterator -
pnpm add response-iterator
Imports
- responseIterator
const responseIterator = require('response-iterator');import responseIterator from 'response-iterator';
Quickstart
import responseIterator from 'response-iterator';
// A polyfill like 'isomorphic-fetch' or 'node-fetch' might be needed for Node.js environments
// if a global `fetch` is not available. For browser, `fetch` is native.
async function fetchData() {
try {
const res = await fetch('https://raw.githubusercontent.com/kmalakoff/response-iterator/master/package.json');
if (!res.ok) {
throw new Error(`HTTP error! status: ${res.status}`);
}
let data = '';
for await (const chunk of responseIterator(res)) {
data += chunk;
}
console.log('Package name:', JSON.parse(data).name); // Expected: "response-iterator"
} catch (error) {
console.error('Failed to fetch or process data:', error);
}
}
fetchData();