Cómo Utilizar la Clase WaitFor para Retrasar el Renderizado de PDF en C#

por Chaknith Bin

Al renderizar documentos PDF, surge un problema común cuando el proceso de renderizado se produce antes de que todos los activos necesarios y la animación de javascript hayan terminado de cargarse. Esto puede dar lugar a una representación incompleta o incorrecta del documento PDF. Inicialmente, abordamos este problema permitiendo al usuario fijar un retraso arbitrario como solución. Sin embargo, confiar en un retraso arbitrario no es un planteamiento fiable ni eficaz.

Para proporcionar una solución más robusta, hemos implementado una clase WaitFor que mejora el proceso de renderizado de PDF. El objeto WaitFor de RenderOptions ofrece varias opciones, entre ellas:


Biblioteca NuGet C# para PDF

Instalar con NuGet

Install-Package IronPdf
o
Java PDF JAR

Descargar DLL

Descargar DLL

Instalar manualmente en su proyecto

Ejemplo de renderización inmediata por defecto

Por defecto, el proceso de renderizado se produce inmediatamente después de que la página haya terminado de cargarse. El método PageLoad no necesita ser llamado si quieres renderizar normalmente.

:path=/static-assets/pdf/content-code-examples/how-to/waitfor-pageload.cs
using IronPdf;

ChromePdfRenderer renderer = new ChromePdfRenderer();

//  Renderizar en cuanto se carga la página
renderer.RenderingOptions.WaitFor.PageLoad();

PdfDocument pdf = renderer.RenderHtmlAsPdf("<h1>testing</h1>");
Imports IronPdf

Private renderer As New ChromePdfRenderer()

'  Renderizar en cuanto se carga la página
renderer.RenderingOptions.WaitFor.PageLoad()

Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf("<h1>testing</h1>")
VB   C#

Ejemplo de retardo de renderizado personalizado

En situaciones en las que se requiere un retardo específico antes de renderizar el PDF, puede establecer un número arbitrario de milisegundos como retardo. De este modo se consigue flexibilidad para adaptarse a cualquier requisito específico de sincronización.

Esta opción funciona de la misma forma que la antigua implementación utilizando la propiedad RenderingOptions.RenderDelay. Sin embargo, la antigua propiedad ha quedado obsoleta, y se recomienda encarecidamente utilizar la nueva API, RenderingOptions.WaitFor.RenderDelay.

:path=/static-assets/pdf/content-code-examples/how-to/waitfor-delay-time.cs
using IronPdf;

ChromePdfRenderer renderer = new ChromePdfRenderer();

//  Renderizado después de 3000ms
renderer.RenderingOptions.WaitFor.RenderDelay(3000);

PdfDocument pdf = renderer.RenderHtmlAsPdf("<h1>testing</h1>");
Imports IronPdf

Private renderer As New ChromePdfRenderer()

'  Renderizado después de 3000ms
renderer.RenderingOptions.WaitFor.RenderDelay(3000)

Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf("<h1>testing</h1>")
VB   C#

Todas las fuentes cargadas Ejemplo

En AllFontsLoaded en el método Espere en permite que el proceso de renderizado del PDF se detenga hasta que se carguen todas las fuentes desde fuentes externas como Google Fonts u otros servidores. Esto garantiza que el PDF final incluya todas las fuentes necesarias, preservando la tipografía y el aspecto visual previstos para el documento.

:path=/static-assets/pdf/content-code-examples/how-to/waitfor-all-fonts.cs
using IronPdf;

string htmlContent = @"
<!DOCTYPE html>
<html lang=""en"">
<head>
  <meta charset=""UTF-8"">
  <title>Test Registration of Extension</title>
  <!-- for google web fonts -->
  <link rel=""preconnect"" href=""https://fonts.googleapis.com"">
  <link rel=""preconnect"" href=""https://fonts.gstatic.com"" crossorigin>
  <link rel=""stylesheet"" href=""https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap"" >

  <style>
  /* for remote fonts */
  @font-face {
    font-family: 'CustomFont';
    src: url('https://stage.gradfinale.co.uk/tcpdf/fonts/avgr65wttf.ttf');
  }
  p#p1 { font-family: CustomFont, sans-serif; }

  /* for local fonts */
  @font-face {
    font-family: 'LocalCustomFont';
    src: local('Arial');
  }
  p#p3 { font-family: LocalCustomFont, sans-serif; }
  </style>
</head>
<body>
	<h1>This is Delayed Render Test!</h1>
	<p style=""font-family: Roboto, monospace;"">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla scelerisque ligula venenatis erat <strong>scelerisque</strong> auctor.</p>
	<p id=""p1"">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla scelerisque ligula venenatis erat <strong>scelerisque</strong> auctor.</p>
	<p id=""p3"">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla scelerisque ligula venenatis erat <strong>scelerisque</strong> auctor.</p>
</body>
</html>)";

ChromePdfRenderer renderer = new ChromePdfRenderer();
renderer.RenderingOptions.WaitFor.AllFontsLoaded(10000);

PdfDocument pdf = renderer.RenderHtmlAsPdf(htmlContent);
IRON VB CONVERTER ERROR developers@ironsoftware.com
VB   C#

Ejemplo de ejecución personalizada de JavaScript

Para un mayor control sobre el proceso de renderizado, nuestra función le permite especificar una función JavaScript personalizada que debe ejecutarse antes de renderizar el documento PDF. Esto le permite realizar cualquier tarea o comprobación necesaria antes de iniciar el proceso de renderizado. De este modo, el usuario controla cuándo se activa el renderizado.

En JavaScript, la función window.ironpdf.notifyRender() se utiliza para activar la tarea de renderizado. Una vez que `notifyRender()se iniciará el proceso de renderizado. Usted tiene pleno control sobre cuándo invocar la función.

:path=/static-assets/pdf/content-code-examples/how-to/waitfor-javascript.cs
using IronPdf;

string html = @"<!DOCTYPE html>
<html>
<body>
<h1>Testing</h1>
<script type='text/javascript'>

//  Fijar retraso
setTimeout(function() {
    window.ironpdf.notifyRender();
}, 1000);

</script>
</body>
</html>";

ChromePdfRenderOptions renderingOptions = new ChromePdfRenderOptions();

//  Configurar el renderizado para esperar a la función notifyRender
renderingOptions.WaitFor.JavaScript(5000);

PdfDocument pdf = ChromePdfRenderer.StaticRenderHtmlAsPdf(html, renderingOptions);
Imports IronPdf

Private html As String = "<!DOCTYPE html>
<html>
<body>
<h1>Testing</h1>
<script type='text/javascript'>

//  Fijar retraso
setTimeout(function() {
    window.ironpdf.notifyRender();
}, 1000);

</script>
</body>
</html>"

Private renderingOptions As New ChromePdfRenderOptions()

'  Configurar el renderizado para esperar a la función notifyRender
renderingOptions.WaitFor.JavaScript(5000)

Dim pdf As PdfDocument = ChromePdfRenderer.StaticRenderHtmlAsPdf(html, renderingOptions)
VB   C#

Ejemplo de elementos HTML

Con esta opción, el proceso de renderizado puede configurarse para esperar elementos HTML específicos, como IDs de elementos, nombres, nombres de etiquetas, e incluso utilizando selectores de consulta para apuntar a elementos.

Esperar ID de elemento

En el siguiente ejemplo de código, el renderizado esperará un ID de elemento específico.

:path=/static-assets/pdf/content-code-examples/how-to/waitfor-html-element-id.cs
using IronPdf;

string htmlContent = @"
<!DOCTYPE html>
<html lang=""en"">
<head>
  <meta charset=""UTF-8"">
  <title>Delayed render tests</title>
  <script type=""text/javascript"">
	setTimeout(function() {
		var h1Tag = document.createElement(""h1"");
		h1Tag.innerHTML = ""bla bla bla"";
		h1Tag.setAttribute(""id"", ""myid"");

        var block = document.querySelector(""div#x"");
		block.appendChild(h1Tag);
	}, 1000);
  </script>
</head>
<body>
	<h1>This is Delayed Render Test!</h1>
    <div id=""x""></div>
</body>
</html>";

ChromePdfRenderer renderer = new ChromePdfRenderer();
renderer.RenderingOptions.WaitFor.HtmlElementById("myid", 5000);

PdfDocument pdf = renderer.RenderHtmlAsPdf(htmlContent);
IRON VB CONVERTER ERROR developers@ironsoftware.com
VB   C#

Esperar nombre de elemento

En el siguiente ejemplo de código, el proceso de renderizado esperará a un elemento específico Nombre.

:path=/static-assets/pdf/content-code-examples/how-to/waitfor-html-element-name.cs
using IronPdf;

string htmlContent = @"
<!DOCTYPE html>
<html lang=""en"">
<head>
  <meta charset=""UTF-8"">
  <title>Delayed render tests</title>
  <script type=""text/javascript"">
	setTimeout(function() {
		var h1Tag = document.createElement(""h1"");
		h1Tag.innerHTML = ""bla bla bla"";
		h1Tag.setAttribute(""name"", ""myName"");

        var block = document.querySelector(""div#x"");
		block.appendChild(h1Tag);
	}, 1000);
  </script>
</head>
<body>
	<h1>This is Delayed Render Test!</h1>
    <div id=""x""></div>
</body>
</html>";

ChromePdfRenderer renderer = new ChromePdfRenderer();
renderer.RenderingOptions.WaitFor.HtmlElementByName("myName", 5000);

PdfDocument pdf = renderer.RenderHtmlAsPdf(htmlContent);
IRON VB CONVERTER ERROR developers@ironsoftware.com
VB   C#

Esperar nombre de etiqueta de elemento

En el ejemplo de código siguiente, el proceso de renderizado esperará un nombre de etiqueta de elemento específico.

:path=/static-assets/pdf/content-code-examples/how-to/waitfor-html-element-tag-name.cs
using IronPdf;

string htmlContent = @"
<!DOCTYPE html>
<html lang=""en"">
<head>
  <meta charset=""UTF-8"">
  <title>Delayed render tests</title>
  <script type=""text/javascript"">
	setTimeout(function() {
		var newElem = document.createElement(""h2"");
		newElem.innerHTML = ""bla bla bla"";

        var block = document.querySelector(""div#x"");
		block.appendChild(newElem);
	}, 1000);
  </script>
</head>
<body>
	<h1>This is Delayed Render Test!</h1>
    <div id=""x""></div>
</body>
</html>";

ChromePdfRenderer renderer = new ChromePdfRenderer();
renderer.RenderingOptions.WaitFor.HtmlElementByTagName("h2", 5000);

PdfDocument pdf = renderer.RenderHtmlAsPdf(htmlContent);
IRON VB CONVERTER ERROR developers@ironsoftware.com
VB   C#

Utilizar el selector de consultas

En el siguiente ejemplo de código, el proceso de renderizado esperará al elemento seleccionado por el selector de consulta. El método HtmlQuerySelector esperará una etiqueta img con id 'myid' y class 'blablastyle'.

:path=/static-assets/pdf/content-code-examples/how-to/waitfor-html-element-query-selector.cs
using IronPdf;

string htmlContent = @"
<!DOCTYPE html>
<html lang=""en"">
<head>
  <meta charset=""UTF-8"">
  <title>Test Registration of Extension</title>
  <script type=""text/javascript"">
	setTimeout(function() {
		var img = document.createElement(""img"");
		img.onload = function() {
			img.setAttribute(""id"", ""myid"");
			img.setAttribute(""class"", ""blablastyle"");
			var block = document.getElementById(""x"");
			block.appendChild(img);
		};
		img.src = ""https://www.w3schools.com/images/picture.jpg""; // .src después de .onload para ignorar la caché, si la hay
	}, 1000);
  </script>
</head>
<body>
	<h1>This is Delayed Render Test!</h1>
    <div id=""x""></div>
</body>
</html>";

ChromePdfRenderer renderer = new ChromePdfRenderer();
renderer.RenderingOptions.WaitFor.HtmlQuerySelector("img#myid.blablastyle", 5000);

PdfDocument pdf = renderer.RenderHtmlAsPdf(htmlContent);
Imports IronPdf

Private htmlContent As String = "
<!DOCTYPE html>
<html lang=""en"">
<head>
  <meta charset=""UTF-8"">
  <title>Test Registration of Extension</title>
  <script type=""text/javascript"">
	setTimeout(function() {
		var img = document.createElement(""img"");
		img.onload = function() {
			img.setAttribute(""id"", ""myid"");
			img.setAttribute(""class"", ""blablastyle"");
			var block = document.getElementById(""x"");
			block.appendChild(img);
		};
		img.src = ""https://www.w3schools.com/images/picture.jpg""; // .src después de .onload para ignorar la caché, si la hay
	}, 1000);
  </script>
</head>
<body>
	<h1>This is Delayed Render Test!</h1>
    <div id=""x""></div>
</body>
</html>"

Private renderer As New ChromePdfRenderer()
renderer.RenderingOptions.WaitFor.HtmlQuerySelector("img#myid.blablastyle", 5000)

Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf(htmlContent)
VB   C#

Ejemplo de red inactiva

Sin actividad en la red

Este tipo de inactividad de la red permite esperar hasta que no haya actividad en la red, lo que suele indicar que el contenido se ha cargado por completo. Esto es adecuado para una aplicación de una sola página (SPA) o una simple página web que no tenga solicitudes de red de larga duración ni actividad de red continua.

El proceso de renderización sólo comenzará cuando no haya ninguna actividad de red en curso durante al menos 500ms.

:path=/static-assets/pdf/content-code-examples/how-to/waitfor-network-idle-0.cs
using IronPdf;

ChromePdfRenderer renderer = new ChromePdfRenderer();

//  Renderizar a menos que no haya habido actividad en la red durante al menos 500 ms.
renderer.RenderingOptions.WaitFor.NetworkIdle0();

PdfDocument pdf = renderer.RenderHtmlAsPdf("<h1>testing</h1>");
Imports IronPdf

Private renderer As New ChromePdfRenderer()

'  Renderizar a menos que no haya habido actividad en la red durante al menos 500 ms.
renderer.RenderingOptions.WaitFor.NetworkIdle0()

Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf("<h1>testing</h1>")
VB   C#

Dos actividades de red permitidas

El método NetworkIdle2 es adecuado para aplicaciones web o páginas web que tienen peticiones de red de larga duración o pings heartbeat. Por lo general, se trata de una o dos solicitudes. En este caso, aunque estas solicitudes estén en curso, no se considerará que invalidan la activación del evento de red inactiva, ya que es aceptable tener como máximo dos de ellas.

Antes de iniciar el proceso de renderizado, debe haber como máximo dos actividades de red restantes durante al menos 500ms. Esta opción proporciona una configuración rápida para gestionar un número fijo de actividades de red.

:path=/static-assets/pdf/content-code-examples/how-to/waitfor-network-idle-2.cs
using IronPdf;

ChromePdfRenderer renderer = new ChromePdfRenderer();

//  Renderizar a menos que haya como máximo 2 actividades de red durante al menos 500ms.
renderer.RenderingOptions.WaitFor.NetworkIdle2();

PdfDocument pdf = renderer.RenderHtmlAsPdf("<h1>testing</h1>");
Imports IronPdf

Private renderer As New ChromePdfRenderer()

'  Renderizar a menos que haya como máximo 2 actividades de red durante al menos 500ms.
renderer.RenderingOptions.WaitFor.NetworkIdle2()

Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf("<h1>testing</h1>")
VB   C#

Personalizar la asignación de actividad de red

En los casos en los que hay varias solicitudes de red implicadas, tiene la flexibilidad de personalizar tanto la duración de inactividad de red como el número de solicitudes de red permitidas que no invalidan la activación del evento de inactividad de red. Esta opción es adecuada para aplicaciones web o páginas web con requisitos específicos que no se ajustan a los dos métodos anteriores. Al ofrecer esta personalización, nos aseguramos de abordar una amplia gama de casos de uso en diferentes circunstancias.

:path=/static-assets/pdf/content-code-examples/how-to/waitfor-customize-network.cs
using IronPdf;

ChromePdfRenderer renderer = new ChromePdfRenderer();

//  Renderizar a menos que haya como máximo 5 actividades de red durante al menos 1000ms
renderer.RenderingOptions.WaitFor.NetworkIdle(1000, 5);

PdfDocument pdf = renderer.RenderHtmlAsPdf("<h1>testing</h1>");
Imports IronPdf

Private renderer As New ChromePdfRenderer()

'  Renderizar a menos que haya como máximo 5 actividades de red durante al menos 1000ms
renderer.RenderingOptions.WaitFor.NetworkIdle(1000, 5)

Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf("<h1>testing</h1>")
VB   C#

Establecer el tiempo máximo de espera

Además, los métodos JavaScript, NetworkIdle, NetworkIdle0, y NetworkIdle2 también permiten establecer un tiempo máximo de espera para asegurar que la espera no será indefinida. Para ello se puede utilizar el parámetro maxWaitTime de estos métodos.

Tenga en cuenta
Todos los valores de tiempo especificados se consideran en milisegundos.

Chaknith Bin

Ingeniero de software

Chaknith es el Sherlock Holmes de los desarrolladores. La primera vez que se le ocurrió que podría tener futuro en la ingeniería de software fue cuando hacía retos de código por diversión. Su trabajo se centra en IronXL e IronBarcode, pero se enorgullece de ayudar a los clientes con todos los productos. Chaknith aprovecha sus conocimientos, adquiridos hablando directamente con los clientes, para ayudar a mejorar los propios productos. Sus comentarios anecdóticos van más allá de los tickets de Jira y apoyan el desarrollo de productos, la documentación y el marketing, para mejorar la experiencia general del cliente.Cuando no está en la oficina, se le puede encontrar aprendiendo sobre aprendizaje automático, codificación y senderismo.