Caching - SharePoint/PnP-JS-Core GitHub Wiki

Often times data doesn't change that quickly, especially in the case of rolling up corporate news or upcoming events. These types of things can be cached for minutes if not hours. To help make caching easy you just need to insert the usingCaching method in your chain. This only applies to get requests. The usingCaching method can be used with the inBatch method as well to cache the results of batched requests.

Basic example

You can use the method without any additional configuration. We have made some default choices for you and will discuss ways to override them later. The below code will get the items from the list, first checking the cache for the value. You can also use it with OData operators such as top and orderBy. The usingCaching() should always be the last method in the chain before the get() (OR if you are using batching these methods can be transposed, more details below).

pnp.sp.web.lists.getByTitle("Tasks").items.usingCaching().get().then(r => {
    console.log(r)
});

pnp.sp.web.lists.getByTitle("Tasks").items.top(5).orderBy("Modified").usingCaching().get().then(r => {
    console.log(r)
});

Globally Configure Cache Settings

If you would like to not use the default values, but don't want to clutter your code by setting the caching values on each request you can configure custom options globally. These will be applied to all calls to usingCaching() throughout your application.

pnp.setup({
    defaultCachingStore: "session", // or "local"
    defaultCachingTimeoutSeconds: 30,
    globalCacheDisable: false // or true to disable caching in case of debugging/testing
});

pnp.sp.web.lists.getByTitle("Tasks").items.top(5).orderBy("Modified").usingCaching().get().then(r => {
    console.log(r)
});

Cache Expiration

Added in 2.0.8

The ability remove of expired items based on a configured timeout can help if the cache is filling up. This can be accomplished in two ways. The first is to explicitly call the new deleteExpired method on the cache you wish to clear. A suggested usage is to add this into your page init code as clearing expired items once per page load is likely sufficient.

import pnp from "sp-pnp-js";

// session storage
pnp.storage.session.deleteExpired();

// local storage
pnp.storage.local.deleteExpired();

// this returns a promise, so you can perform some activity after the expired items are removed:
pnp.storage.local.deleteExpired().then(_ => {
    // init my application
});

The second method is to enable automated cache expiration through global config. Setting the enableCacheExpiration property to true will enable the timer. Optionally you can set the interval at which the cache is checked via the cacheExpirationIntervalMilliseconds property, by default 750 milliseconds is used. We enforce a minimum of 300 milliseconds as this functionality is enabled via setTimeout and there is little value in having an excessive number of cache checks. This method is more appropriate for a single page application where the page is infrequently reloaded and many cached operations are performed. There is no advantage to enabling cache expiration unless you are experiencing cache storage space pressure in a long running page - and you may see a performance hit due to the use of setTimeout.

pnp.setup({
    enableCacheExpiration: true,
    cacheExpirationIntervalMilliseconds: 1000, // optional
});

Per Call Configuration

If you prefer more verbose code or have a need to manage the cache settings on a per request basis you can include individual caching settings for each request. These settings are passed to the usingCaching method call and are defined in the following interface. If you want to use the per-request options you must include the key.

export interface ICachingOptions {
    expiration?: Date;
    storeName?: "session" | "local";
    key: string;
}
pnp.sp.web.lists.getByTitle("Tasks").items.top(5).orderBy("Modified").usingCaching({
    expiration: pnp.util.dateAdd(new Date(), "minute", 20),
    key: "My Key",
    storeName: "local"
}).get().then(r => {
    console.log(r)
});

Using Batching with Caching

You can use batching and caching together, but remember caching is only applied to get requests. When you use them together the methods can be transposed, the below example is valid.

let batch = pnp.sp.createBatch();

pnp.sp.web.lists.inBatch(batch).usingCaching().get().then(r => {
    console.log(r)
});

pnp.sp.web.lists.getByTitle("Tasks").items.usingCaching().inBatch(batch).get().then(r => {
    console.log(r)
});

batch.execute().then(() => console.log("All done!"));