Compartir vía


Paginación e iteración en Azure SDK para Java

En este artículo se proporciona información general sobre cómo usar la funcionalidad de paginación e iteración de Azure SDK para Java para trabajar de forma eficiente y productiva con grandes conjuntos de datos.

Muchas de las operaciones que proporcionadas por las bibliotecas cliente en Azure SDK para Java devuelven más de un resultado. Azure SDK para Java define un conjunto de tipos de valor devueltos aceptables en estos casos para asegurarse de que la experiencia del desarrollador se maximiza a través de la coherencia. Los tipos de valor devueltos que se usan son PagedIterable para las API sincrónicas y PagedFlux para las API asincrónicas. Las API difieren ligeramente en función de sus distintos casos de uso, pero conceptualmente tienen los mismos requisitos:

  • Permite iterar fácilmente todos los elementos de la colección de forma individual, ignorando la necesidad de paginación manual o seguimiento de los tokens de continuación. Tanto PagedIterable como PagedFlux facilitan esta tarea, ya que realizan la iteración de una respuesta paginada deserializada en un tipo determinado T. PagedIterable implementa la interfaz de Iterable y ofrece una API para recibir Stream, mientras que PagedFlux proporciona Flux. En todos los casos, el acto de la paginación es transparente y la iteración continúa mientras haya resultados en los que realizar la iteración.

  • Permite realizar una iteración página a página de forma explícita. Hacerlo no solo permite saber con mayor claridad cuándo se realizan las solicitudes, sino también acceder a la información de respuesta por página. Tanto PagedIterable como PagedFlux tienen métodos que devolverán los tipos adecuados para iterar por página, en lugar de por elemento individual.

Este artículo se divide entre las API sincrónicas y asincrónicas de Azure SDK para Java. Las API de iteración sincrónicas aparecerán al trabajar con clientes sincrónicos y las API de iteración asincrónicas al trabajar con clientes asincrónicos.

Paginación e iteración sincrónicas

En esta sección se tratan las API sincrónicas.

Iteración de elementos individuales

Como se ha indicado, lo más habitual es que las iteraciones se realicen en cada elemento individualmente, en lugar de por página. Los ejemplos de código siguientes muestran la forma en que la API PagedIterable permite usar el estilo de iteración que se prefiera para implementar esta funcionalidad.

Uso de un bucle "for-each"

Dado que PagedIterable implementa Iterable, se puede realizar una iteración por los elementos como se muestra en el ejemplo siguiente:

PagedIterable<Secret> secrets = client.listSecrets();
for (Secret secret : secrets) {
   System.out.println("Secret is: " + secret);
}

Uso de Stream

Dado que PagedIterable tiene un método stream() definido, se le puede llamar para usar las API Stream de Java, como se muestra en el ejemplo siguiente:

client.listSecrets()
      .stream()
      .forEach(secret -> System.out.println("Secret is: " + secret));

Uso de Iterator

Dado que PagedIterable implementa Iterable, también tiene un método iterator() que permite usar el estilo de programación de iteradores de Java, como se muestra en el ejemplo siguiente:

Iterator<Secret> secrets = client.listSecrets().iterator();
while (it.hasNext()) {
   System.out.println("Secret is: " + it.next());
}

Iteración por páginas

Cuando se trabaja con páginas individuales, la iteración se puede realizar por página, por ejemplo, cuando se necesita información de una respuesta HTTP o cuando los tokens de continuación son importantes para conservar el historial de iteraciones. Independientemente de que la iteración se realice por página o por elemento, no hay ninguna diferencia en el rendimiento ni en el número de llamadas que se realizan al servicio. La implementación subyacente carga la siguiente página a petición y si se cancela la suscripción de PagedFlux en cualquier momento, no habrá más llamadas al servicio.

Uso de un bucle "for-each"

Cuando se llama a listSecrets(), se obtiene un elemento PagedIterable, que tiene una API iterableByPage(). Esta API genera un elemento Iterable<PagedResponse<Secret>>, en lugar de Iterable<Secret>. PagedResponse proporciona los metadatos de respuesta y accede al token de continuación, como se muestra en el ejemplo siguiente:

Iterable<PagedResponse<Secret>> secretPages = client.listSecrets().iterableByPage();
for (PagedResponse<Secret> page : secretPages) {
   System.out.println("Response code: " + page.getStatusCode());
   System.out.println("Continuation Token: " + page.getContinuationToken());
   page.getElements().forEach(secret -> System.out.println("Secret value: " + secret))
}

También hay una sobrecarga de iterableByPage que acepta un token de continuación. Si se desea volver al mismo punto de iteración más adelante, se puede llamar a esta sobrecarga.

Uso de Stream

En el ejemplo siguiente se muestra la forma en que el método streamByPage() realiza la misma operación que se mostró anteriormente. Esta API también tiene una sobrecarga de tokens de continuación para volver al mismo punto de iteración en un momento posterior.

client.listSecrets()
      .streamByPage()
      .forEach(page -> {
          System.out.println("Response code: " + page.getStatusCode());
          System.out.println("Continuation Token: " + page.getContinuationToken());
          page.getElements().forEach(secret -> System.out.println("Secret value: " + secret))
      });

Observación asincrónica de páginas y elementos individuales

En esta sección se tratan las API asincrónicas. En las API asincrónicas, las llamadas de red se producen en un subproceso diferente al principal que llama a subscribe(). Esto significa que el subproceso principal puede finalizar antes de que el resultado esté disponible. Es responsabilidad suya comprobar que la aplicación no finalice antes de que la operación asincrónica haya tenido tiempo de completarse.

Observación de elementos individuales

En el ejemplo siguiente se muestra la forma en que la API PagedFlux permite observar elementos individuales asincrónicamente. Hay varias maneras de suscribirse a un tipo Flux. Para más información, consulte el apartado en el que se indican formas sencillas de crear un elemento Flux o Mono, y de suscribirse a él, en la Guía de referencia de Reactor 3. Este ejemplo es una variedad en la que hay tres expresiones lambda, una para el consumidor, otra para el consumidor de errores y una tercera para el consumidor de finalización. Se recomienda tener las tres, pero en algunos casos solo es necesario tener la primera y, posiblemente, la segunda.

asyncClient.listSecrets()
   .subscribe(secret -> System.out.println("Secret value: " + secret),
       ex -> System.out.println("Error listing secrets: " + ex.getMessage()),
       () -> System.out.println("Successfully listed all secrets"));

Observación de páginas

En el ejemplo siguiente se muestra la forma en que PagedFlux API permite observar cada página asincrónicamente, una vez más mediante una API byPage() y proporcionando un consumidor, un consumidor de errores y un consumidor de finalización.

asyncClient.listSecrets().byPage()
  .subscribe(page -> {
          System.out.println("Response code: " + page.getStatusCode());
          System.out.println("Continuation Token: " + page.getContinuationToken());
          page.getElements().forEach(secret -> System.out.println("Secret value: " + secret))
      },
      ex -> System.out.println("Error listing pages with secret: " + ex.getMessage()),
      () -> System.out.println("Successfully listed all pages with secret"));

Pasos siguientes

Ahora que tiene ciertas nociones de paginación y iteración en Azure SDK para Java, considere la posibilidad de leer el artículo Operaciones de larga duración en Azure SDK para Java. Las operaciones de larga son aquellas que se ejecutan durante más tiempo que la mayoría de las solicitudes HTTP normales, habitualmente porque requieren que el servidor trabaje.