Skip to content

Commit

Permalink
Merge pull request #3005 from bcameron1231/v4-docs-iterators
Browse files Browse the repository at this point in the history
Async Iterator Updates
  • Loading branch information
juliemturner authored Apr 20, 2024
2 parents 79dca02 + c002113 commit 31d6e96
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 98 deletions.
71 changes: 0 additions & 71 deletions docs/graph/behaviors.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,77 +30,6 @@ await graph.users();

> DefaultInit and DefaultHeaders are separated to make it easier to create your own default headers or init behavior. You should include both if composing your own default behavior.
## Paged

_Added in 3.4.0_

The Paged behavior allows you to access the information in a collection through a series of pages. While you can use it directly, you will likely use the `paged` method of the collections which handles things for you.

> Note that not all entity types support `count` and where it is unsupported it will return 0.
Basic example, read all users:

```TypeScript
import { graphfi, DefaultHeaders } from "@pnp/graph";
import "@pnp/graph/users";

const graph = graphfi().using(DefaultHeaders());

const allUsers = [];
let users = await graph.users.top(300).paged();

allUsers.push(...users.value);

while (users.hasNext) {
users = await users.next();
allUsers.push(...users.value);
}

console.log(`All users: ${JSON.stringify(allUsers)}`);
```

Beyond the basics other query operations are supported such as filter and select.

```TypeScript
import { graphfi, DefaultHeaders } from "@pnp/graph";
import "@pnp/graph/users";

const graph = graphfi().using(DefaultHeaders());

const allUsers = [];
let users = await graph.users.top(50).select("userPrincipalName", "displayName").filter("startswith(displayName, 'A')").paged();

allUsers.push(...users.value);

while (users.hasNext) {
users = await users.next();
allUsers.push(...users.value);
}

console.log(`All users: ${JSON.stringify(allUsers)}`);
```

And similarly for groups, showing the same pattern for different types of collections

```TypeScript
import { graphfi, DefaultHeaders } from "@pnp/graph";
import "@pnp/graph/groups";

const graph = graphfi().using(DefaultHeaders());

const allGroups = [];
let groups = await graph.groups.paged();

allGroups.push(...groups.value);

while (groups.hasNext) {
groups = await groups.next();
allGroups.push(...groups.value);
}

console.log(`All groups: ${JSON.stringify(allGroups)}`);
```

## Endpoint

This behavior is used to change the endpoint to which requests are made, either "beta" or "v1.0". This allows you to easily switch back and forth between the endpoints as needed.
Expand Down
37 changes: 10 additions & 27 deletions docs/sp/items.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ console.log(items2);

### Get Paged Items

Working with paging can be a challenge as it is based on skip tokens and item ids, something that is hard to guess at runtime. To simplify things you can use the getPaged method on the Items class to assist. Note that there isn't a way to move backwards in the collection, this is by design. The pattern you should use to support backwards navigation in the results is to cache the results into a local array and use the standard array operators to get previous pages. Alternatively you can append the results to the UI, but this can have performance impact for large result sets.
Working with paging can be a challenge as it is based on skip tokens and item ids, something that is hard to guess at runtime. To simplify things you can use the new Async Iterator functionality on the Items class to assist.

```TypeScript
import { spfi } from "@pnp/sp";
Expand All @@ -41,35 +41,18 @@ import "@pnp/sp/items";

const sp = spfi(...);

// basic case to get paged items form a list
const items = await sp.web.lists.getByTitle("BigList").items.getPaged();

// you can also provide a type for the returned values instead of any
const items = await sp.web.lists.getByTitle("BigList").items.getPaged<{Title: string}[]>();

// the query also works with select to choose certain fields and top to set the page size
const items = await sp.web.lists.getByTitle("BigList").items.select("Title", "Description").top(50).getPaged<{Title: string}[]>();

// the results object will have two properties and one method:

// the results property will be an array of the items returned
if (items.results.length > 0) {
console.log("We got results!");

for (let i = 0; i < items.results.length; i++) {
// type checking works here if we specify the return type
console.log(items.results[i].Title);
}
// Using async iterator to loop through pages of items in a large list
for await (const items of sp.web.lists.getByTitle("BigList").items()) {
console.log(items);
break; // closes the iterator, returns
}

// the hasNext property is used with the getNext method to handle paging
// hasNext will be true so long as there are additional results
if (items.hasNext) {
//using async iterator in combination with top() to get pages of items in chunks of 10
for await (const items of sp.web.lists.getByTitle("BigList").items.top(10)) {
console.log(items);
break; // closes the iterator, returns
}

// this will carry over the type specified in the original query for the results array
items = await items.getNext();
console.log(items.results.length);
}
```

### getListItemChangesSinceToken
Expand Down
2 changes: 2 additions & 0 deletions docs/transition-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,5 @@ As an updated pattern we are recommending you move to an async iterator pattern
With that in mind we've removed the `/items/get-all` endpoint. In addition we've updated the @pnp/sp package's `IItems` and `_Items` collections as well as the @pnp/graph `IGraphQueryableCollection` to support the async iterator pattern.

Check out this example for more information on this pattern: [Get Paged Items](./sp/items.md#get-paged-items).

For advanced async patterns: [Async Paging](./concepts/async-paging.md).

0 comments on commit 31d6e96

Please sign in to comment.