> ## Documentation Index
> Fetch the complete documentation index at: https://docs.markpdf.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# Streaming y trabajos asincrónicos

> Consuma /convert/stream y maneje 202 (auto-asíncrono) con SDK de Bun.

# Streaming y trabajos asincrónicos

Como en API, existen dos mecanismos diferentes:

1. **Transmisión de respuesta** (`/convert/stream`): fragmentos de Markdown progresivo mientras el servidor convierte, leyendo el archivo directamente desde el disco con `Bun.file`.
2. **Trabajos por saturación** (`202`): cuando todos los backends están ocupados, la solicitud se pone en cola y se responde a `202` con un `job_id`. Consulte [`GET /jobs/{id}`](/docs/public/es/api/jobs).

## Transmitiendo con `convertStream`

```ts theme={null}
const client = new MarkpdfClient({ apiKey: "YOUR_API_KEY" });

for await (const chunk of client.convertStream("./report.pdf")) {
  process.stdout.write(chunk);
}
```

`convertStream` es un `AsyncGenerator<string>`; úselo con `for await...of`. Internamente, abre `Bun.file(path)` y lo transmite al cuerpo de `POST /convert/stream`, por lo que el archivo completo nunca se carga en la memoria antes de enviarlo.

<CodeGroup>
  ```ts Local file theme={null}
  for await (const chunk of client.convertStream("./report.pdf", { slim: true })) {
    handle(chunk);
  }
  ```

  ```ts Bun.serve — pass-through al cliente theme={null}
  Bun.serve({
    async fetch(req) {
      const url = new URL(req.url);
      const pdfPath = url.searchParams.get("path")!;

      const stream = new ReadableStream({
        async start(controller) {
          const encoder = new TextEncoder();
          for await (const chunk of client.convertStream(pdfPath)) {
            controller.enqueue(encoder.encode(chunk));
          }
          controller.close();
        },
      });

      return new Response(stream, { headers: { "content-type": "text/markdown" } });
    },
  });
  ```
</CodeGroup>

### `streamSlimStrategy`

```ts theme={null}
client.convertStream("./report.pdf", { slim: true, streamSlimStrategy: "sampled" });
```

* `"off"`: streaming puro por página, sin detección de ruido. TTFB mínimo.
* `"sampled"` (predeterminado): muestra las primeras páginas y luego genera por página.
* `"full"`: materializa el documento completo antes de su emisión. Mejor limpieza, peor TTFB.

Consulte [Parámetros](/docs/public/es/api/parameters#streaming-only-parameters).

<Note />

## Empleos por saturación (202)

De forma predeterminada, `convertFile`, `convertBytes` y `convertFromUrl` manejan `202` de forma transparente (`autoPoll: true` en el cliente):

```ts theme={null}
// SDK waits and polls automatically
const markdown = await client.convertFile("./report.pdf");
```

### Manual de encuestas

```ts theme={null}
import { MarkpdfJobQueuedError } from "@markpdf/bun";

try {
  const markdown = await client.convertFile("./report.pdf", { autoPoll: false });
} catch (err) {
  if (err instanceof MarkpdfJobQueuedError) {
    console.log(`En cola: ${err.jobId}`);
    const status = await client.waitForJob(err.jobId, { pollIntervalMs: 5000 });

    if (status.status === "completed") {
      const markdown = status.body as string;
    } else {
      throw new Error(status.error);
    }
  } else {
    throw err;
  }
}
```

`waitForJob` equivale a llamar a `getJob` en un bucle respetando `retry_after_seconds`, pero encapsulado.

<Tip>
  En condiciones de carga normales, no verá `202`; solo sucede cuando todos los backends están saturados. `autoPoll: true` (el valor predeterminado) ya lo cubre sin código adicional en la mayoría de los casos.
</Tip>

<Warning>
  Los resultados de los trabajos completados caducan en aproximadamente 1 hora. Si guarda un `jobId` y recibe `404` al consultarlo, reenvíe la conversión original.
</Warning>
