Страница через коллекцию с помощью пакетов SDK Microsoft Graph
Статья
По соображениям производительности коллекции сущностей часто разбиваются на страницы, и каждая страница возвращается с URL-адресом следующей страницы. Класс PageIterator упрощает использование страничных коллекций. PageIterator обрабатывает перечисление текущей страницы и запрос последующих страниц автоматически.
Заголовки запросов
Если вы отправляете дополнительные заголовки запросов в исходном запросе, эти заголовки не включаются по умолчанию в последующие запросы страницы. Если эти заголовки требуется отправлять в последующие запросы, их необходимо явно настроить.
Итерации по всем сообщениям
В следующем примере показано перебор всех сообщений в почтовом ящике пользователя.
Совет
В этом примере задается небольшой размер страницы с top помощью параметра для демонстрационных целей. Вы можете задать размер страницы до 999, чтобы свести к минимуму количество необходимых запросов.
var messages = await graphClient.Me.Messages
.GetAsync(requestConfiguration =>
{
requestConfiguration.QueryParameters.Top = 10;
requestConfiguration.QueryParameters.Select = new string[] { "sender", "subject", "body" };
requestConfiguration.Headers.Add("Prefer", "outlook.body-content-type=\"text\"");
});
var pageIterator = PageIterator<Message,MessageCollectionResponse>
.CreatePageIterator(
graphClient,
messages,
// Callback executed for each item in
// the collection
(m) =>
{
Console.WriteLine(m.Subject);
return true;
},
// Used to configure subsequent page
// requests
(req) =>
{
// Re-add the header to subsequent requests
req.Headers.Add("Prefer", "outlook.body-content-type=\"text\"");
return req;
}
);
await pageIterator.IterateAsync();
// Makes request to fetch mails list.
let response: PageCollection = await client
.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.
let callback: PageIteratorCallback = (data) => {
console.log(data.subject);
return true;
};
// A set of request options to be applied to
// all subsequent page requests
let 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
let pageIterator = new PageIterator(client, response, callback, requestOptions);
// This iterates the collection until the nextLink is drained out.
await pageIterator.iterate();
MessageCollectionPage messagesPage = graphClient.me().messages()
.buildRequest(new HeaderOption("Prefer", "outlook.body-content-type=\"text\""))
.select("Sender,Subject,Body")
.top(10)
.get();
while(messagesPage != null) {
final List<Message> messages = messagesPage.getCurrentPage();
final MessageCollectionRequestBuilder nextPage = messagesPage.getNextPage();
if (nextPage == null) {
break;
} else {
messagesPage = nextPage.buildRequest(
// Re-add the header to subsequent requests
new HeaderOption("Prefer", "outlook.body-content-type=\"text\"")
).get();
}
}
Важно!
Пакет SDK Microsoft Graph для Go в настоящее время находится в предварительной версии. Использование этого пакета SDK в рабочей среде не поддерживается.
import (
abstractions "github.com/microsoft/kiota-abstractions-go"
msgraphcore "github.com/microsoftgraph/msgraph-sdk-go-core"
"github.com/microsoftgraph/msgraph-sdk-go/me"
"github.com/microsoftgraph/msgraph-sdk-go/models"
)
headers := abstractions.NewRequestHeaders()
headers.Add("Prefer", "outlook.body-content-type=\"text\"")
query := me.MessagesRequestBuilderGetQueryParameters{
Select: []string{"body", "sender", "subject"},
}
options := me.MessagesRequestBuilderGetRequestConfiguration{
Headers: headers,
QueryParameters: &query,
}
result, err := client.Me().Messages().Get(context.Background(), &options)
// Initialize iterator
pageIterator, err := msgraphcore.NewPageIterator(
result, client.GetAdapter(), models.CreateMessageCollectionResponseFromDiscriminatorValue)
// Any custom headers sent in original request should also be added
// to the iterator
pageIterator.SetHeaders(headers)
// Iterate over all pages
iterateErr := pageIterator.Iterate(context.Background(), func(pageItem interface{}) bool {
message := pageItem.(models.Messageable)
fmt.Printf("%s\n", *message.GetSubject())
// Return true to continue the iteration
return true
})
Остановка и возобновление итерации
В некоторых сценариях для выполнения других действий требуется остановить процесс итерации. Можно приостановить итерацию, вернувшись false из обратного вызова итерации. Итерацию можно возобновить, вызвав resume метод в PageIterator.
int count = 0;
int pauseAfter = 25;
var messages = await graphClient.Me.Messages
.GetAsync(requestConfiguration =>
{
requestConfiguration.QueryParameters.Top = 10;
requestConfiguration.QueryParameters.Select = new string[] { "sender", "subject" };
});
var pageIterator = PageIterator<Message, MessageCollectionResponse>
.CreatePageIterator(
graphClient,
messages,
(m) =>
{
Console.WriteLine(m.Subject);
count++;
// If we've iterated over the limit,
// stop the iteration by returning false
return count < pauseAfter;
}
);
await pageIterator.IterateAsync();
while (pageIterator.State != PagingState.Complete)
{
Console.WriteLine("Iteration paused for 5 seconds...");
await Task.Delay(5000);
// Reset count
count = 0;
await pageIterator.ResumeAsync();
}
let count: number = 0;
let pauseAfter: number = 25;
let response: PageCollection = await client
.api('/me/messages?$top=10&$select=sender,subject')
.get();
let callback: PageIteratorCallback = (data) => {
result = `${result}${data.subject}\n`;
console.log(data.subject);
count++;
// If we've iterated over the limit,
// stop the iteration by returning false
return count < pauseAfter;
};
let pageIterator = new PageIterator(client, 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();
}
// not supported in java SDK
Важно!
Пакет SDK Microsoft Graph для Go в настоящее время находится в предварительной версии. Использование этого пакета SDK в рабочей среде не поддерживается.
import (
abstractions "github.com/microsoft/kiota-abstractions-go"
msgraphcore "github.com/microsoftgraph/msgraph-sdk-go-core"
"github.com/microsoftgraph/msgraph-sdk-go/me"
"github.com/microsoftgraph/msgraph-sdk-go/models"
)
headers := abstractions.NewRequestHeaders()
headers.Add("Prefer", "outlook.body-content-type=\"text\"")
query := me.MessagesRequestBuilderGetQueryParameters{
Select: []string{"body", "sender", "subject"},
}
options := me.MessagesRequestBuilderGetRequestConfiguration{
Headers: headers,
QueryParameters: &query,
}
result, err := client.Me().Messages().Get(context.Background(), &options)
// Initialize iterator
pageIterator, err := msgraphcore.NewPageIterator(
result, client.GetAdapter(), models.CreateMessageCollectionResponseFromDiscriminatorValue)
// Any custom headers sent in original request should also be added
// to the iterator
pageIterator.SetHeaders(headers)
// Pause iterating after 25
var count, pauseAfter = 0, 25
// Iterate over all pages
iterateErr := pageIterator.Iterate(context.Background(), func(pageItem interface{}) bool {
message := pageItem.(models.Messageable)
count++
fmt.Printf("%d: %s\n", count, *message.GetSubject())
// Once count = 25, this returns false,
// Which pauses the iteration
return count < pauseAfter
})
// 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
iterateErr = pageIterator.Iterate(context.Background(), func(pageItem interface{}) bool {
message := pageItem.(models.Messageable)
count++
fmt.Printf("%d: %s\n", count, *message.GetSubject())
// Return true to continue the iteration
return true
})