Página por meio de uma coleção usando os SDKs do Microsoft Graph
Artigo
Por motivos de desempenho, as coleções de entidades geralmente são divididas em páginas e cada página é retornada com uma URL para a próxima página. A classe PageIterator simplifica o consumo de coleções de páginas.
O PageIterator manipula a enumeração da página atual e a solicitação de páginas subsequentes automaticamente.
Se você enviar cabeçalhos de solicitação adicionais em sua solicitação inicial, esses cabeçalhos não serão incluídos por padrão em solicitações de página subsequentes. Se esses cabeçalhos precisam ser enviados em solicitações subsequentes, você deve defini-los explicitamente.
Iterar em todas as mensagens
O exemplo a seguir mostra iterando todas as mensagens na caixa de correio de um usuário.
Dica
Este exemplo define um pequeno tamanho de página usando o top parâmetro para fins de demonstração. Você pode definir o tamanho da página até 999 para minimizar o número de solicitações necessárias.
const response: PageCollection = await graphClient
.api('/me/messages?$top=10&$select=sender,subject,body')
.header('Prefer', 'outlook.body-content-type="text"')
.get();
// A callback function to be called for every item in the collection.
// This call back should return boolean indicating whether not to
// continue the iteration process.
const callback: PageIteratorCallback = (message: Message) => {
console.log(message.subject);
return true;
};
// A set of request options to be applied to
// all subsequent page requests
const requestOptions: GraphRequestOptions = {
// Re-add the header to subsequent requests
headers: {
Prefer: 'outlook.body-content-type="text"',
},
};
// Creating a new page iterator instance with client a graph client
// instance, page collection response from request and callback
const pageIterator = new PageIterator(
graphClient,
response,
callback,
requestOptions,
);
// This iterates the collection until the nextLink is drained out.
await pageIterator.iterate();
Parar e retomar a iteração
Alguns cenários exigem interromper o processo de iteração para executar outras ações. É possível pausar a iteração retornando false do retorno de chamada de iteração. A iteração pode ser retomada chamando o resume método no PageIterator.
var pageSize int32 = 10
query := users.ItemMessagesRequestBuilderGetQueryParameters{
Select: []string{"body", "sender", "subject"},
Top: &pageSize,
}
options := users.ItemMessagesRequestBuilderGetRequestConfiguration{
QueryParameters: &query,
}
result, err := graphClient.Me().Messages().Get(context.Background(), &options)
if err != nil {
log.Fatalf("Error getting messages: %v\n", err)
}
// Initialize iterator
pageIterator, err := graphcore.NewPageIterator[*models.Message](
result,
graphClient.GetAdapter(),
models.CreateMessageCollectionResponseFromDiscriminatorValue)
if err != nil {
log.Fatalf("Error creating page iterator: %v\n", err)
}
// Pause iterating after 25
var count, pauseAfter = 0, 25
// Iterate over all pages
err = pageIterator.Iterate(
context.Background(),
func(message *models.Message) bool {
count++
fmt.Printf("%d: %s\n", count, *message.GetSubject())
// Once count = 25, this returns false,
// Which pauses the iteration
return count < pauseAfter
})
if err != nil {
log.Fatalf("Error iterating over messages: %v\n", err)
}
// Pause 5 seconds
fmt.Printf("Iterated first %d messages, pausing for 5 seconds...\n", pauseAfter)
time.Sleep(5 * time.Second)
fmt.Printf("Resuming iteration...\n")
// Resume iteration
err = pageIterator.Iterate(
context.Background(),
func(message *models.Message) bool {
count++
fmt.Printf("%d: %s\n", count, *message.GetSubject())
// Return true to continue the iteration
return true
})
if err != nil {
log.Fatalf("Error iterating over messages: %v\n", err)
}
int iterations = 1;
ArrayList<Message> messages = new ArrayList<>();
int pauseAfter = iterations*25;
MessageCollectionResponse messageResponse = graphClient.me().messages().get( requestConfiguration -> {
requestConfiguration.queryParameters.top = 10;
requestConfiguration.queryParameters.select = new String[] {"sender, subject"};
});
PageIterator<Message, MessageCollectionResponse> pageIterator =
new PageIterator.Builder<Message, MessageCollectionResponse>()
.client(graphClient)
.collectionPage(Objects.requireNonNull(messageResponse))
.collectionPageFactory(MessageCollectionResponse::createFromDiscriminatorValue)
.requestConfigurator( requestInfo -> {
requestInfo.addQueryParameter("%24select", new String[] {"sender, subject"});
requestInfo.addQueryParameter("%24top", 10);
return requestInfo;
})
.processPageItemCallback( message -> {
messages.add(message);
// Pause paging by returning false after 25 messages
return messages.size() < pauseAfter;
}).build();
pageIterator.iterate();
// Resume paging
while (pageIterator.getPageIteratorState() != PageIterator.PageIteratorState.COMPLETE) {
iterations+=1;
pageIterator.resume();
}
$count = 0;
$messages = $graphClient->me()
->messages()
->get()
->wait();
// Microsoft\Graph\Core\Tasks\PageIterator
$pageIterator = new PageIterator($messages, $graphClient->getRequestAdapter());
$callback = function($message) use (&$count): bool {
/** @var Models\Message $message */
$count++;
print($count.'. '.$message->getSubject().PHP_EOL);
// Return true to continue iteration
// Return false once first 5 have been processed
return $count < 5;
};
$pageIterator->iterate($callback);
print('Pausing iteration after first 5'.PHP_EOL);
sleep(5);
// Process next 5
$count = 0;
$pageIterator->iterate($callback);
let count = 0;
const pauseAfter = 25;
const response: PageCollection = await graphClient
.api('/me/messages?$top=10&$select=sender,subject,body')
.get();
const callback: PageIteratorCallback = (message: Message) => {
console.log(message.subject);
count++;
// If we've iterated over the limit,
// stop the iteration by returning false
return count < pauseAfter;
};
const pageIterator = new PageIterator(graphClient, response, callback);
await pageIterator.iterate();
while (!pageIterator.isComplete()) {
console.log('Iteration paused for 5 seconds...');
await new Promise((resolve) => setTimeout(resolve, 5000));
// Reset count
count = 0;
await pageIterator.resume();
}
Solicitando manualmente páginas subsequentes
Como alternativa ao uso da classe PageIterator, você pode marcar manualmente a resposta de uma @odata.nextLink propriedade e solicitar a próxima página.
var messages = await graphClient.Me.Messages
.GetAsync(requestConfiguration =>
{
requestConfiguration.QueryParameters.Top = 10;
});
while (messages?.Value != null)
{
foreach (var message in messages.Value)
{
Console.WriteLine(message.Subject);
}
// If OdataNextLink has a value, there is another page
if (!string.IsNullOrEmpty(messages.OdataNextLink))
{
// Pass the OdataNextLink to the WithUrl method
// to request the next page
messages = await graphClient.Me.Messages
.WithUrl(messages.OdataNextLink)
.GetAsync();
}
else
{
// No more results, exit loop
break;
}
}