API de streams de Node.js
El binding nativo pdf-oxide ofrece streams de lectura para resultados de búsqueda, páginas y tablas — idiomáticos para los pipelines de Node.js y eficientes en memoria para documentos grandes.
Todos los streams implementan la interfaz estándar Readable de Node.js en modo objeto, admiten backpressure, se integran con pipe() y funcionan con la iteración asíncrona for await.
Los streams son nativos del binding de Node.js. Para el build WASM, itera de forma síncrona.
SearchStream
Emite un SearchResult cada vez, a medida que el SearchManager subyacente produce coincidencias.
const { PdfDocument, SearchManager, SearchStream } = require("pdf-oxide");
const doc = new PdfDocument("large.pdf");
const manager = new SearchManager(doc);
const stream = new SearchStream(manager, "invoice");
stream.on("data", (r) => {
console.log(`page ${r.pageIndex + 1}: ${r.text}`);
});
stream.on("end", () => {
console.log("search complete");
doc.close();
});
stream.on("error", (err) => {
console.error(err);
doc.close();
});
Búsqueda sensible a mayúsculas
const stream = new SearchStream(manager, "Invoice", { caseSensitive: true });
Iteración asíncrona
for await (const result of stream) {
if (result.pageIndex > 50) break;
console.log(result.text);
}
Compatibilidad con pipe()
const { Writable } = require("stream");
const sink = new Writable({
objectMode: true,
write(result, _enc, cb) {
console.log(`${result.pageIndex}:${result.text}`);
cb();
},
});
stream.pipe(sink);
PageIteratorStream
Emite el texto extraído de una página cada vez. Útil para salida orientada a líneas o cuando alimentas un LLM con una cola limitada por tasa.
const { PageIteratorStream } = require("pdf-oxide");
const stream = new PageIteratorStream(doc, { format: "markdown" });
for await (const { pageIndex, content } of stream) {
await indexPage(pageIndex, content);
}
format acepta "text" (por defecto), "markdown", "html", "plain".
TableStream
Emite una tabla cada vez, a medida que se detecta.
const { TableStream } = require("pdf-oxide");
const stream = new TableStream(doc);
stream.on("data", (table) => {
console.log(`${table.rows.length}x${table.rows[0].length} on page ${table.pageIndex}`);
});
Backpressure
Todos los streams implementan el backpressure estándar de Node.js. Si tu consumidor es lento, el stream pausa la extracción hasta que .read() se reanuda:
stream.on("data", async (result) => {
stream.pause();
await slowIndex(result);
stream.resume();
});
O usa for await, que gestiona la pausa automáticamente.
Manejo de errores
Los errores durante la extracción se emiten como eventos error estándar:
stream.on("error", (err) => {
if (err.code === "PDF_INVALID_PAGE") {
console.warn("skipping invalid page", err.pageIndex);
} else {
throw err;
}
});
Eficiencia de memoria
Los streams mantienen un solo resultado en curso. En un PDF de 10.000 páginas que produce 50.000 coincidencias, un SearchStream usa memoria constante — el conjunto completo de resultados nunca se materializa.
Limpieza
Cerrar el PdfDocument padre finaliza todos los streams asociados. Los streams también liberan la referencia a su manager al producirse end / error.
const doc = new PdfDocument("big.pdf");
const stream = new SearchStream(new SearchManager(doc), "TODO");
stream.on("end", () => doc.close());
stream.on("error", () => doc.close());
En Node.js 22+, la palabra clave using libera el documento cuando se sale del scope:
{
using doc = new PdfDocument("big.pdf");
const stream = new SearchStream(new SearchManager(doc), "TODO");
for await (const r of stream) console.log(r);
} // doc.close() called automatically
Relacionado
- Primeros pasos con Node.js — instalación, inicio rápido
- Referencia de la API de Node.js
- Búsqueda — opciones de búsqueda sin streaming